React-hot-loader: Docs are unclear on babel plugin vs webpack plugin

Created on 15 Jan 2019  路  17Comments  路  Source: gaearon/react-hot-loader

Description

The https://github.com/gaearon/react-hot-loader#-hot-labs- section mentions that the webpack plugin is "required", but the getting started section doesn't include it.

Expected behavior

It should be clear whether or not the webpack plugin is required

Actual behavior

It's unclear whether it is required or not

Environment

React Hot Loader version: 4.6.3

Reproducible Demo

n/a

Most helpful comment

Yep:

  • babel-plugin _registers_ top level variables, and let us hot update __classes__
  • webpack-loader _registers_ top level variables, and patches react-dom
  • hot-loader/react-dom is just patched react-dom

We need:

  • register top level variables to remove false positives. Ie better know what we are doing
  • inject magic methods to be able to hot update class non-prototype based members

But actually, only tracking of top level variables is __required__. Without it, things could go REALLY WRONG.

All 17 comments

There are 3 options:

  1. use webpack plugin to patch React
  2. use hot-loader/react-dom - already patched react version
  3. do not use anything.

Webpack and babel plugins are not interchangeable - they are doing absolutely different work.

Confusing indeed. So just to confirm. We add react-hot-loader/babel to .babelrc AND do one of the three mentioned? webback plugin, hot-loader/react-dom or nothing. Because the babel patch has nothing to do with patching react-dom? correct?

Yep:

  • babel-plugin _registers_ top level variables, and let us hot update __classes__
  • webpack-loader _registers_ top level variables, and patches react-dom
  • hot-loader/react-dom is just patched react-dom

We need:

  • register top level variables to remove false positives. Ie better know what we are doing
  • inject magic methods to be able to hot update class non-prototype based members

But actually, only tracking of top level variables is __required__. Without it, things could go REALLY WRONG.

@theKashey

What are the expected errors if we just use the babel-loader and the react-hot-loader babel plugin? I'm getting hot reloading working, and I haven't patched anything...

This is under the webpack plugin header:

We recommend to use babel plugin, but there are situations when you are unable to use it

Seems like the babel plugin is in fact an alternative to the webpack plugin, or it is at least the webpack plugin is potentially optional.

In addition to the README being unclear, the error message here implies that the babel plugin is not required when the webpack plugin is used.

@theKashey, thanks for explaining the above, that answers some questions, but I still have a couple more specific questions:

  • Since both babel-plugin and webpack-loader are registering top level variables, does that mean I should not use both together?

  • Patching react-dom: What is this for? Babel-plugin doesn't do this, right? Is that something that is required (babel-plugin alone is never enough)? Just trying to understanding what I get if I use only babel-plugin.

  • Without babel-plugin to work with classes, does that mean hot-loader can only work on functional components that use hooks for state? Just trying to understand what I get if I use only webpack-loader.

Still quite confused - thanks!

  • webpack-loader would do nothing if babel-plugin already did something
  • patching react-dom is essential to support hooks. It also removes some side effects, like complicated type comparison
  • without babel-loader it cant update arrow class methods. Prototype-based methods, including .bind ones are working good.

I also found the documentation confusing, and I find many of the explanations in this thread confusing as well.

I think the readme could be WAY more readable with these changes:

  1. Remove the 馃敟HOT-LABS馃敟 section

    • it says the Webpack plugin is required (even though it isn't)
    • it mentions react-馃敟-dom - something you might not need, and you haven't even read the 'getting started' section yet!
    • there is no helpful info in this section
  2. Move the React-馃敟-Dom section right under getting started

    • If you need hooks support, you can just follow 'Getting Started' and then move on to this section

It seems like the Webpack plugin is for very advanced use cases - it is "not compatible with class-based components"? That seems insane. I wouldn't mention it until much later in the document.

I would submit a pull request for this if people like.

I'm really confused how the getting-started section's point 3, the webpack plugin section, the React-馃敟-Dom section, and the hot-labs section all have different or overlapping suggestions for how to accomplish patching react-dom. Is it enough to follow steps 1-3 in the getting-started section, or is there something else that should be done too? If there is something extra necessary, can it be made a step 4 inside the getting started section? If step 3 is sufficient, but there are alternatives, can they be moved to be bullet points directly under step 3, so it's clear they are alternatives? (Also, hooks are officially part of React now, so if any of the alternatives don't work with hooks, they should be listed last and specifically called out as being less capable.)

Remove the 馃敟HOT-LABS馃敟 section

+1

Remove the 馃敟HOT-LABS馃敟 section

:+1:

To be honest - readme becomes a bit long, wordy and not quite clear. Feel free to make it better.

Okay I took a stab at this here: https://github.com/gaearon/react-hot-loader/pull/1232

I liked your idea @Macil of adding a 4th step, so I did that.

If the Webpack plugin really is a useful thing, I think I would need more help understanding it to add that to the getting started section. What can it be used alongside? What does it replace?

Let me summon @tannerlinsley, he hold a bit different opinion on Webpack loader.

After trying literally every single combination of configurations, I landed on one that seems to give the most stability. Keep in mind, this configuration is for React Static (which is a CLI and build tool) so it needs to cover a lot of use cases with very little assumptions and setup on the user end. It also has to be the smallest and least invasive configuration as possible, so as to not break or get in the way of users that are attempting to customize babel configurations or webpack configurations.

  • We use the webpack-dev-server module to run our dev server with the hotOnly: true setting.
  • Prepend your webpack config's entry array with react-hot-loader/patch. This should make it irrelevant whether you import react-hot-loader before react in your own code. Nice!
  • Add new webpack.HotModuleReplacementPlugin() to your webpack plugins. Easy.
  • Add the react-hot-loader/webpack loader after your javascript/typescript loader (usually babel-loader). This loader must run on both your src and node_modules files since it's responsible for patching both react and your own react components to hot-reload correctly.
  • Add to your application's index.js:
import { AppContainer } from 'react-hot-loader'
...
const render = Comp => {
  ReactDOM.render( // or ReactDOM.hydrate in production
    <AppContainer>
      <Comp />
    </AppContainer>,
    document.getElementById('root')
  )
}

// Render for the first time
render(App)

// Hot Module Replacement
if (module && module.hot) {
  module.hot.accept('./App', () => {
    // Render updates
    render(App)
  })
}
  • 馃憥 you will be unable to update non-prototype based Component methods (like onClick)
  • 馃憥 as long as webpack-plugin works only with module.exports, while babel-plugin works with all top-level variables, it may lead to some false-positives during class update sometimes (read - might broke during refactoring)
  • 馃憤 module.hot.accept and render are still the best options to trigger an update, but not always play well with code splitting.

1232 merged, but lets keep this issue open for a while for the next improvements.

I'm about to add react-hot-loader to my webpack/babel-7-setup. The 3rd step confuses me:

3. Make sure react-hot-loader is required before react and react-dom:
  - or import 'react-hot-loader' in your main file (before React)
  - or prepend your webpack entry point with react-hot-loader/patch

What exactly would you have to do now? Or what would be a mistake, in the example above there is no react-import at all.

I think an example for each of the 3 options would be quite good? Here it is, as I understand it:

Make sure react-hot-loader is required before react and react-dom:

// hot must be imported before react
import { hot } from 'react-hot-loader/root';
import React from 'react';
import ReactDOM from 'react-dom';

import 'react-hot-loader' in your main file (before React)

// bootstrap.js
import "react-hot-loader";

// app.js
import "./bootstrap.js";
// your other code

prepend your webpack entry point with react-hot-loader/patch

// webpack.config.js
module.exports = {
  entry: [ "react-hot-loader/patch", "src/index.js"],
}

RHL shall be imported before React, or it may lead to the situation when React will import RHL, then RHL will import React, and then again.

And there are many way to do it, and you got all of them right.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

theKashey picture theKashey  路  3Comments

jljorgenson18 picture jljorgenson18  路  3Comments

Opty1712 picture Opty1712  路  4Comments

calvinchankf picture calvinchankf  路  3Comments

lemonmade picture lemonmade  路  3Comments