Enable Hot Module Replacement(HMR) in Nrwl/Nx React Project
Tags: nrwl, react, hmr, nx
Published: 2021-05-14 20:15:13

HMR offer many benefits. Here is a quote from the [official webpack website](https://webpack.js.org/concepts/hot-module-replacement/):
>Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload. This can significantly speed up development in a few ways:

>Retain application state which is lost during a full reload.

>Save valuable development time by only updating what's changed.

>Instantly update the browser when modifications are made to CSS/JS in the source code, which is almost comparable to changing styles directly in the browser's dev tools.

Nrwl/Nx for React doesn't come with HMR by default. There is a long-standing [issue](https://github.com/nrwl/nx/issues/1881) for this and I waited for a workable solution for a long time, and finally, we got it. So the solution is in the issue and this blog is to save everybody's time trying to piece together a workable solution.

1. Add below to package.json in the devDependencies section and install. ```json
 "webpack": "^4.46.0", (5.x doesn't work)
 "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
 "react-refresh": "^0.10.0",
 ```
2. Create a new file webpack.config.js or another name, to host your custom webpack configuration, I put it in my app folder
{% gist https://gist.github.com/rexebin/4a809161c0b82facaf4787f67f9ea8bc %}
3. Edit workspace.json to configure Nx to use the above custom webpack configuration.
Find `projects/[your app]/targets/build/options` section, add this line to the end of the options section: `"webpackConfig": "[path to]/webpack.config.js`. ([your app] is your app's name.)
Mine looks like this:
{% gist https://gist.github.com/rexebin/1cdc6771b85b66ff941642436e3e7cee %}
4. update file .babelrc to add react-refresh/babel plugin. Mine looks like this:
{% gist https://gist.github.com/rexebin/feb5bd8aa63023810b5061009b7cada1 %}

After above, you would see something like this in your console:

>[WDS] App updated. Recompiling...
>reloadApp.js:19 [WDS] App hot update...
>log.js:24 [HMR] Checking for updates on the server...
>log.js:24 [HMR] Updated modules:
>log.js:24 [HMR] - ../../../libs/[path of changed file here]
>log.js:24 [HMR] App is up to date.

What I love about it is that I know exactly when the app is up to date, no more guessing. It is so much better than the silent console of Create React App. I had to go to the Network tab to see if the app is updated; I ended up refreshing the browser most of the time to be sure the update has taken place.

Update: 25/05/2021

After two weeks of using the shining new HMR above, I am back to report that I am very happy with the solution. 

I repeat, I love that NX tells me when exactly the app is hot loaded and up to date, making it better than react-react-app, which is silence on hot reload in the console(last time I tried, two months back).

A few things to note:

1. stick to one export per file to make HMR work consistently
1. when adding/removing hooks, HMR fails and an error message appears. make sense, nothing to complain
1. react-refresh catches all console error messages and make them full screen, at first it is kinda annoying because of some vendor error, then I realised that it is there for a good reason, it forces me to fix the errors even if it is from third-party libraries, from which I always learn something new.