Using react-hot-loader with a webpack-dev-server and a node server

May 14th, 2015 | expressjs, hot reloading, nodejs, react, webpack |

2015-12-31: You should check out my recent post to use the new way of doing HR with webpack, and to have way more details :
Webpack Hot Reloading and React : how ?

Don’t work without hot-reloading

I got a project running its own Node server instance, using expressjs. It’s already bundling its assets with webpack, and it’s using React with the nice ES6 features, all good.

But it lacks of hot reloading. :-(

This is something we must have nowadays when you’re working with webapps and CSS/Javascript. You don’t want to refresh your whole page and lose your current state each time, you are going to lose your time, your patience, and your productivity !

Leave express alone and add webpack-dev-server on top

Thus, I decided to take a look and tried to add it while keeping the express server instance up and working. I didn’t want to replace the whole thing by a webpack-dev-server and reconfigure the public assets paths and all other stuff that my expressjs was providing.

After some tests, some readings here and there, I got a pretty straightforward solution without using any custom proxy code, nor changing my generated html.

The solution

For reference:
– the expressjs server is running on localhost:3000
– the webpack-dev-server is going to run on localhost:3001

Here is a git diff of my changes:

packages.json

+ "react-hot-loader": "^1.2.7",
+ "webpack-dev-server": "^1.8.2"

Just the necessary packages to do the hot reloading. (npm install --save-dev)

webpack.config.js

+var webpack = require('webpack');

- entry: path.resolve(__dirname, '../src/client.js'),
+ entry: [
+   'webpack-dev-server/client?http://0.0.0.0:3001',
+   'webpack/hot/only-dev-server',
+   path.resolve(__dirname, '../src/client.js')
+ ],

modules: {
  loaders: [
    {
-     loader: 'babel-loader'
+     loaders: [ 'react-hot-loader', 'babel-loader' ]
    }
  ]
},

+ plugins: [
+   new webpack.HotModuleReplacementPlugin(),
+   new webpack.NoErrorsPlugin()
+ ]

– we add webpack-dev-server entries into entry
– we add the react-hot-loader loader when processing the .js (it will add some js to magically do the hot reloading)
– we add the plugins for hot reloading.

More details here http://gaearon.github.io/react-hot-loader/getstarted/

server.js

This is the most important part, where we define a new webpack-dev-server instance that will be listen by the browser to process the hot reloading if any js file change.

// existing express server
var app = express();
app.use(...)
app.get(...)
app.listen(3000);

+// we start a webpack-dev-server with our config
+var webpack = require('webpack');
+var WebpackDevServer = require('webpack-dev-server');
+var config = require('./webpack.config.js');

+new WebpackDevServer(webpack(config), {
+   hot: true,
+   historyApiFallback: true,
+   proxy: {
+     "*": "http://localhost:3000"
+   }
+}).listen(3001, 'localhost', function (err, result) {
+   if (err) {
+     console.log(err);
+   }
+
+   console.log('Listening at localhost:3001');
+});

We are only adding a new webpack-dev-server instance without altering at all our expressjs server listening on localhost:3000.

– our webpack-dev-server listens to localhost:3001 and handle the hotness
– every requests (“*”) are redirected to localhost:3000.

This server serves only as a proxy for the hot reloading. More details here http://webpack.github.io/docs/webpack-dev-server.html.

At the end, there is still no hot reloading on http://localhost:3000 (it’s still a pure expressjs server).

But if you browse http://localhost:3001, and more precisely http://localhost:3001/webpack-dev-server/, you will the famous “App ready” hot reloading toolbar and everything will be automatically updated if you change one of your React component.

Published by

ctheu

Hey. I love computer sciences almost since I'm born. I work with frontend and backend technologies; I can't make my mind ! Let's share some tips about how some of them work, shall we ?

  • Chris GW Green

    Ctheu, you’ve made my day! I’m so impressed with that solution.

  • Vladimir Avilov

    @Ctheu, thx for your solution, but i have one problem, on url “http://localhost:3001/webpack-dev-server/” hot load work, but on http://localhost:3001 – not( Could this be due to the fact that I use react-router?

  • Alan

    This helped me out incredibly! Exactly what I was looking for. Thank you so much.

    • Alan

      I literally just saw this blog post for the same exact problem I had two months earlier and found I had commented on it. How embarrassing.

  • Thanks ctheu. I have been developing for decades but am very new to Node so frequently it is the little things like this that mess me up. This worked great.

  • hi.. this is great but i’m looking a solution for multiple entries. Do you mind advise?

  • Anders Ramsay

    Hi – would you by chance have a repo with a complete example you could share? For example, I’m not clear what would go in the app.use and app.get calls.