神刀安全网

Webpack’s HMR & React-Hot-Loader — The Missing Manual

Webpack’s HMR along with React-Hot-Loader makes developing React apps very productive. But depending on the type of the React app (client and server) you are building, setting them up could be challenging. Further, Webpack itself is very flexible and provides various ways to enable HMR and some of them may not be good for YOUR app.

So in this blog I’ll go over 3 ways of enabling up Webpack’s HMR and then go over 3 React app scenarios and show how to set them up. I’ll also cover some of the “confusing” parts along the way :grinning: .

But first, a quick refresher about HMR..

Webpack HMR Brief Overview

Webpack’s Hot Module Replacement (HMR) allows you to replace updated modules without reloading the browser. It needs webpack-dev-server and the following 4 parts in order to work.

  1. Libraries injected into the browser to perform HMR (webpack hmr)
  2. Libraries in the browser to listen to changes in the server( i.e. webSocket client)
  3. Needs to know if “hot” is enabled and other info from the server (webSocket info from webpack-dev-server)
  4. Needs a plugin to generate hot chunks that contain the changed parts (HMRPlugin).

You can learn more from my previous post Webpack And The HMR

OK, let’s go over different ways of enabling Webpack’s HMR…

There are 3 different ways to enable Webpack’s HMR itself. And then depending on your app’s scenario, you can choose one of them and then use React Hot Loader along with it.

Enable HMR Method 1 — Webpack’s CLI

This is probably the simplest that works for most cases but not for all. You need to pass inline and hot to enable HMR (all 4 part mentioned earlier).

1. inline option

→ This injects all the libraries required to monitor and reload the browser

2. hotoption

→ Adds HotModuleReplacementPlugin that generates update chunks.

→ Adds ‘ webpack/hot/dev-server ’ to every entry (single or multiple).

→ Sets WDS’ “hot” to true {hot:true} so relevant code for HMR is enabled

Below are the ways to run HMR via CLI.

//1. WDS is installed globally
webpack-dev-server --inline --hot
//2. WDS is installed as a dev-dependency
node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot
//3. from package.json's script
{
...
"scripts": {
"start": "webpack-dev-server --inline --hot"
}
...
}
You can run by from CLI by doing: npm start

Enable HMR Method 2 — webpack.config.js

Instead of passing hot and inline via CLI, we can configure all of that inside the webpack.config.js file.

One of the advantages is that you can choose between “ /hot/dev-server” Vs “/hot/only-dev-server” (You’ll learn the difference later in this blog)

Below is an example webpack.config.js that enables HMR in it’s simplest form.

Webpack’s HMR & React-Hot-Loader — The Missing Manual
webpack.config.js w/ HMR

You can then run this from CLI like below. Notice that there is no “inline” and “hot”.

//1. WDS is installed globally
webpack-dev-server
//2. WDS is installed as a dev-dependency
node_modules/webpack-dev-server/bin/webpack-dev-server.js
//3. from package.json's script
{
...
"scripts": {
"start": "webpack-dev-server
}
...
}

Important: Use either CLI or Config file but never mix and match the above two ways.

FYI — webpack.config.js (contentBase)

If your index.html is in a different folder like “public”, make sure to set contentBase to point to that.

Webpack’s HMR & React-Hot-Loader — The Missing Manual

Enable HMR Method 3 — Via NPM Module

Webpack-dev-server itself is a wrapper around an Express server and deals with core Webpack and WebSocket. Webpack-dev-server exposes itself and the Express server as a Node module. So you can create a JS file and use WDS like another Express server (i.e. a custom WDS) and pass arguments.

The below picture shows how to do that. Notice that it still needs webpack.config.js for core Webpack configuration details.

Note: you can click on the picture to zoom and read

Webpack’s HMR & React-Hot-Loader — The Missing Manual
custom-web-dev-server.js

You run this custom webpack-dev-server from the terminal by calling: “npm custom-web-dev-server.js”

The above code is fromDan Abramov’s React Hot Reloader example .

Note: Some projects use this capability to add the above WDS code to their Node.js server’s file itself so they can run both servers in a single Terminal (in different ports) and with a single command.

OK, now let’s see how to add different loaders for 3 different App scenarios…

App Scenario 1 — A Simple React App

In a very basic React app that doesn’t even make API calls likeDan Abramov’s React Hot Reloader example , it’s very simple to add and use loaders like style-loader & react-hot-loader t hat implement Webpack’s HMR feature.

Adding Style-Loader or React-Hot-Loader

In order to enable HMR for CSS and React modules, all you need to do is to add the following loaders.

npm install react-hot-loader --save-dev
npm install style-loader --save-dev

And then add the loaders to the Webpack’s config file like below.

Webpack’s HMR & React-Hot-Loader — The Missing Manual
Showing react-hot-loader and style-loader

“loaders” Vs “loader” inside “loaders”

In the above picture, if you look carefully, you might notice that for react-hot-loader added as part of an Array where as for style-loader is part of a String ! In addition, the property name for the former is called “loaders” (plural) and the latter is called “loader”(singular) . :scream:

It turns out, they both are the SAME but just different ways of piping multiple loaders for a single file format.

Webpack’s HMR & React-Hot-Loader — The Missing Manual

Thanks Sokra (Webpack creator) for clarifying that .

“/hot/only-dev-server” Vs “/hot/dev-server”

They both are simple JS libraries and provide HMR interface for webpack-dev-server’s client JS(part of WDS) that’s also loaded into the browser (See my Webpack And The HMR for more details).

You can use just one of them. The main difference is as follows:

  1. only-dev-server doesn’t reload the browser upon syntax errors. This is recommended for React apps because it keeps the state.
  2. dev-server tries HMR (default). If there is any issue, it reloads the entire browser.
Webpack’s HMR & React-Hot-Loader — The Missing Manual

Note: If you are using the CLI with — inline and — hot, dev-server is automatically added (and not the only-dev-server)

App Scenario 2— A React App With Backend API calls (proxy)

Let’s say we have a React app that makes an API call to the server that’s running in port 3000. For example, the below picture tries to get the server’s time by calling “ /api/serverTime ”. Without WDS, it will be calling http://localhost:3000/api/serverTime

Webpack’s HMR & React-Hot-Loader — The Missing Manual

But, when running inside webpack-dev-server that’s running on port 8080 means we are calling http://localhost:8080/api/serverTime! As you know WDS only serves static files has no idea about that API.

Webpack’s HMR & React-Hot-Loader — The Missing Manual

Even if we hardcoded the path like: “ http://localhost:3000/api/serverTime ”, then we’ll see cross-domain error like so:

Webpack’s HMR & React-Hot-Loader — The Missing Manual

To solve this situation, which is very common BTW, you can use WDS’s “ proxy ” property like below. Now, every time the browser makes the call to /api/*, WDS sends that info to the real backend server (running at 3000).

Webpack’s HMR & React-Hot-Loader — The Missing Manual

Note: You can use /api/v1/* or /api/v2/* to switch and test different versions of the backend server APIs.

App Scenario 3— A React App With Backend Server That’s BOTH API AND Web Server

This is also a common scenario where the server is acting as both API and web server.

Imagine you have an Express server that’s running in port 3000 that serves html by compiling index.ejs at https://localhost:3000 and serves html by compiling users.ejs at https://localhost:3000/users

Now, Imagine these ejs files simply include React’s bundle.js like so:

Webpack’s HMR & React-Hot-Loader — The Missing Manual
index.ejs at localhost:3000

In production it’s fine because the webserver will compile the ejs and return the html but during development w/ HMR we have a problem! We NEED Express (at 3000) to generate HTML from ejs.

The below picture shows the scenario.

Webpack’s HMR & React-Hot-Loader — The Missing Manual
Shows the scenario of API+Web server

The solution is to proxy everything with a “*” star.

Webpack’s HMR & React-Hot-Loader — The Missing Manual
proxy everything w/ *

FYI — publicPath overrides proxy settings

The below picture shows the Express server logs(at port 3000) when we refresh the browser(at 8080). Notice that the webpack-dev-server has proxied:

1. “/” (to load index file from compiled index.ejs),

2. “/stylesheets/style.css” (to load style.css)

3. “/api/serverTime” (to return serverTime api value).

Webpack’s HMR & React-Hot-Loader — The Missing Manual
Web + API Server

But, it has not proxied the“ /static/bundle.js ”. This is because in our config file, we have publicPath set to ‘/static/’ and webpack-dev-server gives priority to this over the proxy (even though we have set it to *).

Webpack’s HMR & React-Hot-Loader — The Missing Manual
since it matches /static/, “/static/bundle.js” is served from localhost:8080 itself instead of proxying it

This means if you are loading bundle.js from a different directory that doesn’t match publicPath settings (you’ll have to setup ANOTHER proxy on the Express server that’s running on port 3000 (that points back to localhost:8080). This will be super confusing.

Also, you don’t have to use publicPath at all. If you don’t set it or set it to ‘/’, just make sure that the ejs files load bundle.js like so:

<script src=”/bundle.js”></script>

That’s it! :pray:

My Other Posts

WebPack

  1. Webpack — The Confusing Parts
  2. Webpack & Hot Module Replacement [HMR] (under-the-hood)
  3. Webpack’s HMR And React-Hot-Loader — The Missing Manual

Draft.js

  1. Why Draft.js And Why You Should Contribute
  2. How Draft.js Represents Rich Text Data

React And Redux :

  1. Step by Step Guide To Building React Redux Apps
  2. A Guide For Building A React Redux CRUD App (3-page app)
  3. Using Middlewares In React Redux Apps
  4. Adding A Robust Form Validation To React Redux Apps
  5. Securing React Redux Apps With JWT Tokens
  6. Handling Transactional Emails In React Redux Apps
  7. The Anatomy Of A React Redux App

Salesforce

  1. Developing React Redux Apps In Salesforce’s Visualforce

:tada::tada::tada: If you like this post, please 1. ❤❤❤ it below on Medium and 2. please share it on Twitter. You may retweet the below card :tada::tada::tada:

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Webpack’s HMR & React-Hot-Loader — The Missing Manual

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址