ctrlplusb
ctrlplusb

Reputation: 13147

Supporting webpack dependant imports during node dev server execution (a React server rendering context)

I have a universal React project configured in which I use Webpack to create bundles for both the client and the server code.

This works fine when I run the server directly via the targetting the bundled output by Webpack.

 node ./build/server/main.js

However I am having issues though when I try to run a "live" development server. In this case I don't want to target the bundled server files, instead I just target the source files directly which will allow me to run the webpack hot middleware for live code changes. Below is a stripped down version of the main file for the server.


src/server/index.js

import express from 'express'
import universalReactAppMiddleware from './middleware/universalReactApp'

const server = express()

// Get the client bundle webpack configuration.
const webpackClientConfig = require('../../webpack.client.config.js')

// If we are in development mode we will add the webpack hot 
// reloading middleware.
if (process.env.NODE_ENV === 'development') {
  const webpack = require('webpack')
  const clientCompiler = webpack(webpackClientConfig)
  const createWebpackMiddleware = require('webpack-dev-middleware')
  const createWebpackHotMiddleware = require('webpack-hot-middleware')
  server.use(
    createWebpackMiddleware(clientCompiler, {
      noInfo: true,
      publicPath: webpackClientConfig.output.publicPath,
      stats: {
        colors: true,
        hash: false,
        timings: true,
        chunks: false,
        chunkModules: true,
        modules: false
      }
    })
  )
  server.use(
    createWebpackHotMiddleware(clientCompiler)
  )
}

// Configure static serving of our webpack bundled client files.
server.use(
  webpackClientConfig.output.publicPath,
  express.static(webpackClientConfig.output.path))

// Bind our universal react app middleware for all GET requests.
server.get('*', universalReactAppMiddleware)

server.listen(process.env.SERVER_PORT)

An example execution of this now being:

NODE_ENV=development babel-node ./src/server

It starts up okay, but the moment the universalReactAppMiddleware handles a request it will attempt to perform server rendering for a resolved Component. This then falls over because some of my components import images/css, for example:


src/shared/components/Foo

import './styles.css'
import background from './background.jpg'

function FooComponent() {
  return <img src={background} />
}

Computer says no!

Upon execution my express server throws out an exception saying unexpected syntax. It basically tries to parse the css and image imports as Javascript. These types of imports depend on my webpack loaders to operate correctly.


So now I am trying to look for a mechanism of spoofing the Webpack behaviour so that I can execute these types of components. I am investigating Pete Hunts webpack-require but have been having difficulty with it.

Does anyone know of any other approaches that will work for this context?


Update 2016/06/15

Boom! I've managed to pull this off without any 3rd party libs to help me. universal-webpack is pretty cool and much cleaner than the previous webpack-isomorphic-tools but I am liking that I have a minimal configuration set up in which as little as possible of the universal webpack configuration bleeds into my production code.

I'm pretty stoked with the results. Client bundle is backed by the lastest react-hot-loader v3 beta which is giving me an awesome HMR experience, and my Server bundle gets rebuilt on any file changes so not having to restart my server manually either. Making for a pretty sweet development experience.

I am going to throw this into a boilerplate (yes I know, yet another) but perhaps it will be useful to someone else.

Upvotes: 0

Views: 182

Answers (1)

ctrlplusb
ctrlplusb

Reputation: 13147

I created a working solution achieving everything that I wanted from the configuration.

It's all within the following boilerplate repo: https://github.com/ctrlplusb/react-universally

Upvotes: 1

Related Questions