Struggling to set up HMR with Webpack?
Are you finding the Webpack documentation to be lacking - particularly in the HMR section? Does it seem like they've left out some important parts?
If so, read on! We'll fill in the gaps together.
First let's get a couple myths about HMR out of the way.
Myth: HMR is only for React
Myth: HMR is only for 'advanced' users
Not true. Without good documentation, HMR is difficult for beginners and advanced users alike. With the right information (this article), HMR can be enabled with very minor changes to config/code.
Myth: HMR is the same as 'live reload'
Not true. Live reload is when the browser automatically refreshes the page whenever you make a code change. HMR is faster because it updates code in-place without refreshing.
2 Steps to HMR Success
There are 2 steps to enabling HMR: config changes and code changes.
1. Config / Project Setup
There are 3 ways to configure your project for HMR. I go into each way in detail in Part 1. Pick the way that's right for you and either use the provided github repository, or follow the directions to adapt your existing code base.
Part 1: Configuring Your Project
There are exactly 3 ways that you can configure your HMR project. Let's go through each one. I'll help you pick which one to use in the next section.
1. webpack-dev-server CLI
webpack-dev-server on the command-line. With this approach you don't need to change your
webpack.config.js file, so it's the simplest.
2. webpack-dev-server API
WebpackDevServer from a node.js script. Requires some additions to your
3. webpack-hot-middleware w/ express
webpack-hot-middleware is used for running a webpack dev server with HMR inside an express server.
If you are used to running the
webpack CLI or the
Webpack API (without
webpack-dev-server), then you'll have to change how you do things a little bit. HMR requires a server to work. To find out why, read my understanding HMR post.
But how do I choose?
Follow this simple guide to pick one of the 3 ways above.
If you are using a task runner like grunt or gulp you'll want to use the webpack-dev-server API. You can run the server from one of your gulp/grunt tasks.
If you use your own node scripts to run webpack, you'll also want to use the webpack-dev-server API.
If you use express to host your site: use webpack-hot-middleware. It will be integrated with your express server, so you won't have to run another server for your bundled JS.
If none of the above apply to you or you just want the simplest possible setup: use the webpack-dev-server CLI. It requires no configuration.
Okay, I picked one, but how do I start?
Glad you asked! Below is a separate 'Configuring X' section for each of the 3 approaches.
Scroll forward to the approach you decided to use, follow the directions, and then scroll down to Part 2.
1. Configuring webpack-dev-server CLI
Read this section if you've decided to use the
webpack-dev-server CLI. Otherwise, scroll to the next section.
If you are starting a new project, use my webpack HMR with webpack-dev-server CLI starter project (wow that's a mouthful). It has a README and lots of comments to explain what's going on.
If you are working with an existing project: just make sure you have a valid
webpack.config.js and run
Here's an example command:
webpack-dev-server --content-base=www --inline --watch --hot
You may want to modify the above command for your use-case based on the CLI Docs.
That's it! When you use the
webpack-dev-server CLI it does all the configuration for you.
webpack.config.jsdoes NOT contain any references to
HotModuleReplacementPlugin. You'll get errors if you do.
2. Configuring WebpackDevServer API
Read this section if you've decided to use the
WebpackDevServer API. Otherwise, scroll to the next section.
If you are starting a new project, use my webpack HMR with WebpackDevServer API starter project. It has a README and lots of comments to explain what's going on.
If you are working with an existing project, you'll have to make 3 changes:
Change #1: Add entry points to your
webpack.config.js. Here's an example. You need
webpack-dev-server/client as shown, but
index.js should be the name of your usual entry point.
Change #2: Add the
HotModuleReplacementPlugin to your your
webpack.config.js, like this:
For a complete example, see the starter project webpack.config.js.
Change #3: Run
WebpackDevServer with the
hot: true option. For an example, see the starter project server.js.
3. Configuring webpack-hot-middleware & express
Read this section if you've decided to use
webpack-hot-middleware. Otherwise, scroll on to Part 2.
If you are starting a new project, use my webpack HMR with webpack-hot-middleware & express starter project. It has a README and lots of comments to explain what's going on.
If you are working with an existing
express project, you'll need to do 3 things:
Change #1: Install
webpack-dev-middleware. I'm assuming you already have
npm install --save-dev webpack-hot-middleware webpack-dev-middleware
Change #2: Adjust your
webpack.config.js to look similar to this. The important bits are the
plugins section. You'll want all the plugins I have listed:
var path =;var webpack =;var config =context: path.entry:'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000''./index.js'output:path: path.filename: 'bundle.js'publicPath: '/assets/'plugins:new webpack..new webpack.new webpack.;module.exports = config;
Change #3: Add the middleware to your express server.
Add these requires:
var webpackDevMiddleware =;var webpackHotMiddleware =;
And these middleware
Part 2: Code Changes
Your Webpack project should now be configured for HMR. But if you fire up a browser at this point and make a code change, it won't work. Either you won't see the update, or you'll get a full browser refresh.
Why isn't it working yet? Webpack doesn't know when it is acceptable to reload a particular JS file.
module.hotAPI and you will see changes reflected immediately.
The Simple Way
To start, find your entry point (often called
main.js) and add the following to the end:
This tells Webpack that this file and all of its dependencies can be replaced.
Now make a code change that you could see the effect of onscreen. You SHOULD have seen an update!
For many projects, that's all there is to it.
The Catch: Side Effects
If any of your files produce side effects when they run, for instance if they add elements to the DOM, then you'll need to use
module.hot.dispose to dispose of those side effects.
Why? If you don't, when Webpack reloads the module, all the side effects will be repeated.
Here's an example, box-creator.js:
var sideEffectNode = document.;sideEffectNode. = 'Side Effect';document..;// Remove the most recently-added <div> so that when the code runs again and// adds a new <div>, we don't end up with duplicate divs.if module.module..;
This is a file that simply adds a
<div/> to the DOM whenever it is loaded. It uses
module.hot.dispose to remove the
<div/> when it is unloaded by the Webpack HMR Runtime.
That's all you need to know to get HMR working. If you want to dig deeper to solidify your understanding, read my article on understanding HMR.
Coming soon: next I'll post about how to apply HMR to your React project. Sign up for my list to be notified when that comes out!