react项目配置react-hot-loader实现模块热更新

今天我们来聊一聊react的模块热更新,熟悉react的同学都知道,使用官方的脚手架,当我们改动页面时,整个页面会被刷新,那我们当然希望页面只刷新我们改动的部分而不是刷新整个页面,那么怎么做到如此呢?千呼万唤始出来,react-hot-loader就是来完成这个伟大的使命的。

1. 安装react-hot-loader

npm i react-hot-loader --save

2. 在开发环境下添加入口

    entry: [
      isEnvDevelopment && 'react-hot-loader/patch',
      // Include an alternative client for WebpackDevServer. A client's job is to
      // connect to WebpackDevServer by a socket and get notified about changes.
      // When you save a file, the client will either apply hot updates (in case
      // of CSS changes), or refresh the page (in case of JS changes). When you
      // make a syntax error, this client will display a syntax error overlay.
      // Note: instead of the default WebpackDevServer client, we use a custom one
      // to bring better experience for Create React App users. You can replace
      // the line below with these two lines if you prefer the stock client:
      // require.resolve('webpack-dev-server/client') + '?/',
      // require.resolve('webpack/hot/dev-server'),
      isEnvDevelopment &&
        require.resolve('react-dev-utils/webpackHotDevClient'),
      // Finally, this is your app's code:
      paths.appIndexJs,
      // We include the app code last so that if there is a runtime error during
      // initialization, it doesn't blow up the WebpackDevServer client, and
      // changing JS code would still trigger a refresh.
    ].filter(Boolean),

如上,entry的第一行即为我们添加的内容。

3. 在开发环境下配置babel插件

            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),
                
                plugins: [
                  isEnvDevelopment && 'react-hot-loader/babel',
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent: '@svgr/webpack?-svgo,+ref![path]',
                        },
                      },
                    },
                  ],
                ],
                // This is a feature of `babel-loader` for webpack (not Babel itself).
                // It enables caching results in ./node_modules/.cache/babel-loader/
                // directory for faster rebuilds.
                cacheDirectory: true,
                cacheCompression: isEnvProduction,
                compact: isEnvProduction,
              },
            },

如上,plugins配置的第一行:isEnvDevelopment && 'react-hot-loader/babel',即为我们添加的代码,如果配置在.babelrc文件中,则写在.babelrc的plugins配置中。

4. plugins中添加依赖的 HotModuleReplacement 插件

一般情况下,脚手架初始化的项目此步骤已经满足,无需再改动。

plugins: [
        ...
        new webpack.HotModuleReplacementPlugin(), //设置这里
        ...
]

5. 设置 devServer 的 hot 为 true

一般情况下,脚手架初始化的项目此步骤已经满足,无需再改动。

    devServer: {
       ...
        hot: true,  //设置这里
       ...
    },

6. 在项目主入口文件中进行修改

首先,从 react-hot-loader 导入 AppContainer 组件:

import { AppContainer } from 'react-hot-loader';

然后,改写 render 方法:

原 render 为:

ReactDOM.render(
  
    
  ,
  document.getElementById('root')
);

修改之后为:

const render = Component => {
  ReactDOM.render(
    
      
        
      
    ,  
    document.getElementById('root'));
}

然后,执行render函数,继而再写模块热更新时的处理代码:

render(App);

if (module.hot) {
  module.hot.accept('./App', () => {
    //因为在App里使用的是export default语法,这里使用的是require,默认不会加载default的,所以需要手动加上
    const NextApp = require('./App').default;
    // 重新渲染到 document 里面
    render(NextApp);
  })
}

完整的主入口文件为:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from '@/store';
import * as serviceWorker from './serviceWorker';

import { AppContainer } from 'react-hot-loader';

const render = Component => {
  ReactDOM.render(
    
      
        
      
    , 
    document.getElementById('root'));
}


render(App);

if (module.hot) {
  module.hot.accept('./App', () => {
    //因为在App里使用的是export default语法,这里使用的是require,默认不会加载default的,所以需要手动加上
    const NextApp = require('./App').default;
    // 重新渲染到 document 里面
    render(NextApp);
  })
}

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

至此,我们就已经配置完成了react项目的模块热更新,即局部刷新而不是整个页面的刷新,如此可大大提高开发效率。

你可能感兴趣的:(前端,react专区,webpack,react,模块热更新,局部刷新,前端)