使用webpack和React实现热替换

模块热替换(HMR)

概念

  • 在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面
  • 也是用在开发环境中加快效率得一种方式
  • 这个是除了code spliting之外的webpack的另外一个非常重要的功能

模块的热加载和热替换有什么区别呢?

  • 热加载:当修改某一个模块的时候
    • 会触发资源的重新挂载(也就相当于刷新页面)
    • 页面在store中存储的数据以及state数据都会丢失
  • 热替换:当修改某一个模块的时候,
    • 只会触发被修改的模块的重新挂载而不会引发其他模块的重新挂载
    • 不会影响的任何数据

那么如何实现模块的热替换呢?

  • 热替换(HMR):非常类似于React的diff算法,因此搭配react使用很合适

    • 使用React-Hot-Loader
    • webpack-dev-server
    • 其涉及的代码很多
  • 修改webpack的配置

entry: {
    main: [
      'react-hot-loader/patch' //开启react模块的热替换功能
    ]
  },
plugins: [
    new webpack.NamedModulesPlugin(),
    //作用在控制台中显示出项目中那一个模块被修改了
    // [HMR] Updated modules:
    //log-apply-result.js:22 [HMR]  - //./app/src/containers/User/LoginContainer/index.js
    //log-apply-result.js:22 [HMR]  - //./app/src/routes.js
    //log-apply-result.js:22 [HMR]  - //./app/src/Root.js
    //dev-server.js:27 [HMR] App is up to date.
    new webpack.HotModuleReplacementPlugin()
    // 给每个react组件的模块加上hot的相关信息 开启热替换
  ],
devServer: {
    // ... 其他配置
    hot: true,
    // 开启服务器的模块热替换(HMR)
  }
  • 修改.babelrc
{
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ],
  "plugins": [
    "lodash", 
    ["import", {"libraryName": "antd"}]
  ],
  "env": {
    "development": {
      "plugins": [
        "react-hot-loader/babel",  //开启模块热替换
      ]
    },
  }
 //.babelrc中由于热替换仅仅用于开发环境因此只有开发环境包含
 //疑惑的是,网上说需要将es2015De module设置成false,但是我没有设置也成功了很奇怪
}
  • 修改代码分成两个部分:
    • 替换组件
    //index.js(入口文件)
    import {AppContainer as ReactHotLoader} from 'react-hot-loader'
    import { getStoreInstance, history } from './store'
    import { render, unmountComponentAtNode } from 'react-dom'
    
    const MOUNT_NODE = document.getElementById('app')
    const renderApp = () => {
    const Root = require('./Root').default
    render(
      
          
      ,
      MOUNT_NODE
    )
    
    if(process.env.NODE_ENV === 'production' && module.hot){
    //使用module.hot来判断有没有给每个module都加上了热替换的功能
        module.hot.accept('./Root',()=>{
        //检测Root组件和其子组件,只要有module的变化就会调用这个回调函数,进行组件的替换
           unmountComponentAtNode(MOUNT_NODE)
           //将MOUNT_NODE中的所有React组件移除
           renderApp()  //将原来的组件移除,替换上新的组件
        })
    }
    
    

}

- 替换store
```js
  let storeInstance = null
  export const getStoreInstance = function (initialState) {
      return storeInstance || configureStore(initialState)
  }
  
  function configureStore(initialState) {
    storeInstance = createStore(
      rootReducer,
      initialState,
      composedEnhancers,
    )
    if (module.hot) {
      module.hot.accept('./reducers', () => {
        const nextReducer = require('./reducers')
        storeInstance.replaceReducer(nextReducer)
      })
    }
    return storeInstance
  }

你可能感兴趣的:(使用webpack和React实现热替换)