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 hot
ness
– 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.