Skip to content

Commit e904b07

Browse files
SpaceK33zTheLarkInn
authored andcommitted
Improve HMR docs (#389)
* Improve HMR docs * Fix link * Add concept page for HMR * Small improvements Really I just want to trigger a rebuild because the clabot is not working.
1 parent 1d03ea8 commit e904b07

File tree

4 files changed

+143
-356
lines changed

4 files changed

+143
-356
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: Hot Module Replacement
3+
sort: 11
4+
contributors:
5+
- SpaceK33z
6+
- sokra
7+
---
8+
9+
Hot Module Replacement (HMR) exchanges, adds, or removes modules while an
10+
application is running without a page reload. You basically can update changed modules without a full page reload.
11+
12+
## How Does It Work?
13+
14+
### From The App View
15+
16+
The app code asks the HMR runtime to check of updates. The HMR runtime downloads the updates (async) and tell the app code that an update is available. The app code asks the HMR runtime to apply updates. The HMR runtime applies the update (sync). The app code may or may not require user interaction in this process (you decide).
17+
18+
### From The Compiler (webpack) View
19+
20+
In addition to the normal assets the compiler need to emit the "Update" to allow updating from previous version to this version. The "Update" contains two parts:
21+
22+
1. the update manifest (JSON)
23+
2. one or multiple update chunks (JavaScript)
24+
25+
The manifest contains the new compilation hash and a list of all update chunks (2.).
26+
27+
The update chunks contains code for all updated modules in this chunk (or a flag if a module was removed).
28+
29+
The compiler addtionally makes sure that module and chunk ids as consistent between these builds. It uses a "records" json file to store them between builds (on it store them in memory).
30+
31+
### From The Module View
32+
33+
HMR is an opt-in feature, so it only affects modules that contains HMR code. The documentation describes the API that is available in modules. In general the module developer writes handlers that are called when a dependency of this module is updated. The developer can also write a handler that is called when this module is updated.
34+
35+
In most cases it's not mandatory to write HMR code in every module. If a module has no HMR handlers the update bubbles up. This means a single handler can handle a update to a complete module tree. If a single module in this tree is updated, the complete module tree is reloaded (only reloaded not transferred).
36+
37+
### From The HMR Runtime View (Technical)
38+
39+
For the module system runtime is additional code emitted to track module `parents` and `children`.
40+
41+
On the management side the runtime supports two methods: `check` and `apply`.
42+
43+
A `check` does a HTTP request to the update manifest. When this request fails, there is no update available. Elsewise the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk the corresponding update chunk is downloaded. All module updates as stored in the runtime as update. The runtime switches into the `ready` state, meaning an update has been downloaded and is ready to be applied.
44+
45+
For each new chunk request in the ready state the update chunk is also downloaded.
46+
47+
The `apply` method flags all updated modules as invalid. For each invalid module there need to be a update handler in the module or update handlers in every parent. Else the invalid buddles up and mark all parents as invalid too. This process continues until no more "bubble up" occurs. If it bubbles up from an entry point the process fails.
48+
49+
Now all invalid modules are disposed (dispose handler) and unloaded. Then the current hash is updated and all "accept" handlers are called. The runtime switches back to the `idle` state and everything continues as normal.
50+
51+
## What can I do with it?
52+
53+
You can use it in development as LiveReload replacement. webpack-dev-server supports a hot mode which tries to update with HMR before trying to reload the whole page. See how to implement [HMR with React](/guides/hmr-react) for example.
54+
55+
Some loaders already generate modules that are hot-updateable. i.e. the `style-loader` can exchange the stylesheet. You don't need to do anything special.
56+
57+
webpack's power lies in its customizability, and there are *many* ways of configuring HMR given the needs of a particular project.

content/guides/development.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ The command above should automatically open your browser on `http://localhost:80
8686

8787
Make a change in one of your files and hit save. You should see that the console is recompiling. After that's done, the page should be refreshed. If nothing happens in the console, you may need to fiddle with [`watchOptions`](/configuration/dev-server#devserver-watchoptions-).
8888

89-
Now you have live reloading working, you can take it even a step further: Hot Module Replacement. This is an interface that makes it possible to swap modules **without a page refresh**. Find out how to [configure HMR](/guides/hmr).
89+
Now you have live reloading working, you can take it even a step further: Hot Module Replacement. This is an interface that makes it possible to swap modules **without a page refresh**. Find out how to [configure HMR](/guides/hmr-react).
9090

9191
By default **inline mode** is used. This mode injects the client - needed for live reloading and showing build errors - in your bundle. With inline mode you will get build errors and warnings in your DevTools console.
9292

content/guides/hmr-react.md

Lines changed: 85 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ contributors:
66
- jhnns
77
---
88

9-
Hot Module Replacement (HMR) exchanges, adds, or removes modules while an
10-
application is running without a page reload.
9+
As explained in detail on the [concept page](/concepts/hot-module-replacement), Hot Module Replacement (HMR)exchanges, adds, or removes modules while an application is running without a page reload.
1110
HMR is particularly useful in applications using a single state tree,
1211
since components are "dumb" and will reflect the latest application state, even
1312
after their source is changed and they are replaced.
1413

14+
The approach described below uses Babel and
15+
React, but these tools are not necessary for HMR to work.
16+
17+
T> If you'd like to see examples of other approaches, please request them or better yet, [open up a PR with an addition](https://github.com/webpack/webpack.js.org).
18+
1519
## Project Config
1620

1721
This guide will be demonstrating the use of HMR with Babel,
@@ -39,113 +43,109 @@ Your `.babelrc` file should look like the following:
3943
{
4044
"presets": [
4145
["es2015", {"modules": false}],
42-
//Webpack understands the native import syntax, and uses it for tree shaking
46+
// webpack understands the native import syntax, and uses it for tree shaking
4347

4448
"stage-2",
45-
//Specifies what level of language features to activate.
46-
//Stage 2 is "draft", 4 is finished, 0 is strawman.
47-
//See https://tc39.github.io/process-document/
49+
// Specifies what level of language features to activate.
50+
// Stage 2 is "draft", 4 is finished, 0 is strawman.
51+
// See https://tc39.github.io/process-document/
4852

4953
"react"
50-
//Transpile React components to JavaScript
54+
// Transpile React components to JavaScript
5155
],
5256
"plugins": [
5357
"react-hot-loader/babel"
54-
//Enables React code to work with HMR.
58+
// Enables React code to work with HMR.
5559
]
5660
}
5761
```
5862

59-
### Webpack config
63+
### webpack Config
6064

61-
While there's many ways of setting up your Webpack config - via API,
65+
While there's many ways of setting up your webpack config - via API,
6266
via multiple or single config files, etc - here is the basic information
6367
you should have available.
6468

6569
```js
6670
const { resolve } = require('path');
6771
const webpack = require('webpack');
6872

69-
module.exports = env => {
70-
return {
71-
entry: [
72-
'react-hot-loader/patch',
73-
//activate HMR for React
73+
module.exports = {
74+
entry: [
75+
'react-hot-loader/patch',
76+
// activate HMR for React
7477

75-
'webpack-dev-server/client?http://localhost:8080',
76-
//bundle the client for webpack dev server
77-
//and connect to the provided endpoint
78+
'webpack-dev-server/client?http://localhost:8080',
79+
// bundle the client for webpack-dev-server
80+
// and connect to the provided endpoint
7881

79-
'webpack/hot/only-dev-server',
80-
//bundle the client for hot reloading
81-
//only- means to only hot reload for successful updates
82+
'webpack/hot/only-dev-server',
83+
// bundle the client for hot reloading
84+
// only- means to only hot reload for successful updates
8285

8386

84-
'./index.js'
85-
//the entry point of our app
86-
],
87-
output: {
88-
filename: 'bundle.js',
89-
//the output bundle
90-
91-
path: resolve(__dirname, 'dist'),
92-
93-
publicPath: '/'
94-
//necessary for HMR to know where to load the hot update chunks
95-
},
96-
97-
context: resolve(__dirname, 'src'),
98-
99-
devtool: 'inline-source-map',
100-
101-
devServer: {
102-
hot: true,
103-
//activate hot reloading
104-
105-
contentBase: resolve(__dirname, 'dist'),
106-
//match the output path
107-
108-
publicPath: '/'
109-
//match the output publicPath
110-
},
111-
112-
module: {
113-
loaders: [
114-
{ test: /\.js$/,
115-
loaders: [
116-
'babel-loader',
117-
],
118-
exclude: /node_modules/
119-
},
120-
{
121-
test: /\.css$/,
122-
loaders: [
123-
'style-loader',
124-
'css-loader?modules',
125-
'postcss-loader',
126-
],
127-
},
128-
],
129-
},
130-
131-
plugins: [
132-
new webpack.HotModuleReplacementPlugin(),
133-
//activates HMR
134-
135-
new webpack.NamedModulesPlugin(),
136-
//prints more readable module names in the browser console on HMR updates
87+
'./index.js'
88+
// the entry point of our app
89+
],
90+
output: {
91+
filename: 'bundle.js',
92+
// the output bundle
93+
94+
path: resolve(__dirname, 'dist'),
95+
96+
publicPath: '/'
97+
// necessary for HMR to know where to load the hot update chunks
98+
},
99+
100+
context: resolve(__dirname, 'src'),
101+
102+
devtool: 'inline-source-map',
103+
104+
devServer: {
105+
hot: true,
106+
// activate hot reloading
107+
108+
contentBase: resolve(__dirname, 'dist'),
109+
// match the output path
110+
111+
publicPath: '/'
112+
// match the output `publicPath`
113+
},
114+
115+
module: {
116+
loaders: [
117+
{ test: /\.js$/,
118+
loaders: [
119+
'babel-loader',
120+
],
121+
exclude: /node_modules/
122+
},
123+
{
124+
test: /\.css$/,
125+
loaders: [
126+
'style-loader',
127+
'css-loader?modules',
128+
'postcss-loader',
129+
],
130+
},
137131
],
138-
};
132+
},
133+
134+
plugins: [
135+
new webpack.HotModuleReplacementPlugin(),
136+
// activates HMR
137+
138+
new webpack.NamedModulesPlugin(),
139+
// prints more readable module names in the browser console on HMR updates
140+
],
139141
};
140142
```
141143

142144
There's a lot going on above, and not all of it is related to HMR.
143145
You may benefit from reading the
144-
[full documentation](https://webpack.github.io/docs/webpack-dev-server.html)
145-
on webpack dev server, and the [other articles](https://webpack.js.org/concepts/)
146-
here on webpack.js.org.
146+
[webpack-dev-server options](/configuration/dev-server) and the [concept pages](/concepts).
147147

148-
The basic assumption here is that your JavaScript entry is located at `./src/index.js`,
148+
The basic assumption here is that your JavaScript entry is located at `./src/index.js`
149149
and that you're using CSS Modules for your styling.
150150

151151
Please see the comments inline that explain each portion of the config. The main
@@ -154,7 +154,7 @@ also necessary to include in the `plugins` array.
154154

155155
There are two modules included here for the purposes of this guide.
156156
The react-hot-loader addition to the entry, as noted above, is necessary to enable
157-
HMR with React components. The NamedModulesPlugin is a useful addition
157+
HMR with React components. The `NamedModulesPlugin` is a useful addition
158158
to better understand what modules are being updated when using HMR.
159159

160160
### Code
@@ -229,18 +229,18 @@ is included in `App.js`.
229229

230230
### Package.json
231231

232-
Finally, we need to start up webpack dev server to bundle our code and see HMR in action.
232+
Finally, we need to start up webpack-dev-server to bundle our code and see HMR in action.
233233
We can use the following package.json entry:
234234

235235
```json
236236
{
237237
"scripts" : {
238-
"start" : "webpack-dev-server --env.dev"
238+
"start" : "webpack-dev-server"
239239
}
240240
}
241241
```
242242

243-
Run `npm start`, open up your browser to `localhost:8080`,
243+
Run `npm start`, open up your browser to `http://localhost:8080`,
244244
and you should see the following entries printed in your console.log:
245245

246246
```bash
@@ -249,7 +249,7 @@ only-dev-server.js:74[HMR] Waiting for update signal from WDS…
249249
client?c7c8:24 [WDS] Hot Module Replacement enabled.
250250
```
251251

252-
Go ahead and edit and save your App.js file.
252+
Go ahead and edit and save your `App.js` file.
253253
You should see something like the following in your console.log:
254254

255255
```bash
@@ -262,4 +262,4 @@ dev-server.js:27 [HMR] App is up to date.
262262
```
263263

264264
Note that HMR specifies the paths of the updated modules.
265-
That's because we're using the NamedModules plugin.
265+
That's because we're using `NamedModulesPlugin`.

0 commit comments

Comments
 (0)