How to Hot-Load React Component in 7 days. Part 1 (Webpack)

I hope you know how to setup hot (re)loading in Webpack and Redux.

It is a very simply task:

  1. Enable HMR in webpack.
  2. Add module.hot.accept in index.js
  3. Try to enjoy. But it will be hard.
It isn`t gonna work. At least today.
Why? For the glory of HMR of course!

So what actually will not work:

  1. Sometimes, when you update your application — you will NOT see changes.
  2. Sometimes, when you update your application — it will RELOAD everything.
  3. Sometimes, when you update your application — it will REMOUNT every component.

But it will work tomorrow. And you will understand — why.

Part 1 — HRM

HRM — Hot Module Replacement.

A very simple feature both from code side and architecture.

But there is a few moments, that you may NOT understand.

So first step — enable HMR on backend.

You will have to enable hot it dev server, just pass --hot as command line argument to the webpack-dev-server.

Second step — enable HMR _for_ frontend.

To have ability to name modules, you have to add a new plugin — NamedModulePlugin. Only after this you will have ability to execute module.hot.accept(SOME_NAME).

BUT!! HEY!!! I`v just read an article, and found next code:

plugins: [
new webpack.HotModuleReplacementPlugin()
]

Ok, but use NamedModulePlugin, and forget about HotModuleReplacementPlugin. At least for Webpack3.

You can found a different ways to enable something, but just keep in mind — to enable some feature — use that feature provider documentation. From webpack-dev-server point of view — I am right.

Third step — enable HMR on frontend.

Just add if (module.hot) module.hot.accept() in your index.js. This will just means that you accept, and know what to do next with all this….

And next it might work. But I am not sure…

Part 2 — It isn`t gonna work

How HMR works? Everything is simple:

  1. You have a module, and you hot replace it.
  2. Next webpack`s magic will transfer to frontend and update it.
  3. Next HMR will start bubling.
  4. It will check if current module is acceptable. And….
Watch the hands of a magician!!!!!
  1. If module is NOT accepted — it will RELOAD EVERYTHING.
  2. if module IS accepted — it will stop bubbling.
  3. if this is top module it will RELOAD EVERYTHING.
  4. If there is no more parents — module is accepted by passed list of parents, and they ALL will be replaced by a new ones.

So, if you accept changes in index.js it…. will not work :)

You have to understand what is parent in this context. And you also have to understand that module can have more than one parent.

Every file, which import second file — is a Parent for it. Each!

So, lets me save you a bit of time. If you have webpack configuration like

entryPoint({
'common-chunk': ['babel-polyfill','sharedContent/pages'],
'app-entry': './src/app/index.js',
}),

Or you use CommonChunksPlugin. Or do whatever else to split code…

And you import a component page from common, in app — …..

It will reload a page.

As long App is now a parent of a Page. But common-chunk is also a real file, and it is also a real parent of a Page and it will not accept changes.

And it is a top level module, so even if one parent accept changes — second is not.

And this second parent is not editable. How to accept changes???!!!!

Relax, the only thing you should do is to replace set of files with a single one. Just control everything by your own hands.

import 'babel-polyfill';
import 'sharedContent/pages'
if (module.hot) module.hot.accept();

PS: You can just accept here, as long there is no brains in common-chunk. You can accept anything, just to stop bubling, and rely of on real brains in App.

But dynamic chunks from brand new “imports”?

Yep, this is another case. Is is possible, but a bit tricky to create a custom file for them. But there is no need — deferred chunks will be auto-accepts by default. Cos they are from other realty.

Part 3 — rest of configuration.

By this time you will have HMR enabled and working properly. If application still trying to do full page refresh — just check console messages.

At the end of chain you will found a top level module, where you probably should add module.accept.

Last Warning

And, buy working properly I mean — IT WILL NOT WORK.

To have React Hot Reloading you have to catch HMR event in a single point — where you application is mounted to a real world.

You have to remount application.

Or you will not see any visual changes at all. Code will be updated, but your application — will be not.

But, is there any difference between hardreset of full page reload and softreset of full page remount?

We will discus this in a next chapter — How (not) to remount React.

Something to read about:

Like what you read? Give Anton Korzunov a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.