Can't get Webpack 2 HMR React to work

后端 未结 2 746
鱼传尺愫
鱼传尺愫 2020-12-21 06:09

Currently I\'m struggling to get HMR working in my Webpack 2 setup. I\'ll explain my entire setup so I hope this is enough for someone to understand what\'s happening.

相关标签:
2条回答
  • 2020-12-21 06:41

    The imports are static and after an update has been identified in module.hot.accept you render the exact same component again, as the TodoApp still holds the old version of your module and HMR realises that and doesn't refresh or change anything in your app.

    You want to use Dynamic import: import(). To make it work with babel you need to add babel-plugin-syntax-dynamic-import, otherwise it will report a syntax error as it didn't expect import to be used as a function. The react-hot-loader/babel is not needed if you use react-hot-loader/patch in your webpack config, so your plugins in your .babelrc become:

    "plugins": [
      "syntax-dynamic-import"
    ]
    

    In your render() function you can now import the TodoApp and render it.

    const render = () => {
      import('./components/TodoApp').then(({ default: Component }) => {
        ReactDOM.render(
          <AppContainer>
            <Component />
          </AppContainer>,
          document.querySelector('#main')
        );
      });
    };
    
    render();
    
    // Hot Module Replacement API
    if (module.hot) {
      module.hot.accept('./components/TodoApp', render);
    }
    

    import() is a promise that will resolve with the module, and you want to use the default export.


    Even though the above is true, the webpack documentation doesn't require you to use dynamic imports, because webpack handles ES modules out of the box, also described in react-hot-loader docs - Webpack 2, and because webpack is also handling the HMR, it will know what to do in that case. For this to work, you must not transform the modules to commonjs. You did this with ["es2015", {"modules": false}], but you also have the latest preset configured in your webpack config, which also transforms the modules. To avoid confusion, you should have all babel configurations in .babelrc instead of splitting some to the loader options.

    Remove the presets in the babel-loader entirely from your webpack config and it will work as you already have the necessary presets in your .babelrc. babel-preset-latest is deprecated and if you want to use these features you should start using babel-preset-env which also replaces es2015. So your presets in .babelrc would be:

    "presets": [
      ["env", {"modules": false}],
      "react"
    ],
    
    0 讨论(0)
  • 2020-12-21 07:01

    Check this issue on GitHub or just use this in your index.js:

    import React from 'react'
    import ReactDOM from 'react-dom'
    import { AppContainer } from 'react-hot-loader'
    
    import App from './components/App'
    
    const render = Component => { 
        ReactDOM.render(
            <AppContainer>
                <Component/>
            </AppContainer>,
            document.getElementById('react-root')
        )
    }
    
    render(App)
    
    if(module.hot) {
        module.hot.accept();
    }
    
    0 讨论(0)
提交回复
热议问题