模块热替换(hot module replacement )

559 阅读1分钟

也就是大家所说的热加载,主要是通过以下几种方式,来加快开发速度:

  • 保留在完全重新加载页面期间丢失的应用程序状态。
  • 只更新变更内容。
  • 在源代码中对css/js进行更改,会立刻在浏览器中同步更新。相当于在浏览器的devtools直接更改样式。
更多的热更新概念

我们重点来看是如何实现的:

webpack.config.js

...
module.exports = {
  mode: 'development',
  entry: {
    app: './src/index.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './dist',
    hot: true
  },
  ...
};

现在修改index.js文件,以便在print.js发生变更的时候,告诉webpack接收updated module.

index.js

 ...
+
+ if (module.hot) {
+   module.hot.accept('./print.js', function() {
+     console.log('Accepting the updated printMe module!');
+     printMe();
+   })
+ }

修改print.js里面的console

  export default function printMe() {
-   console.log('I get called from print.js!');
+   console.log('Updating print.js...')
  }

这个时候,我们看控制台的console.可能你会发现继续点击示例上的按钮,仍然打印旧的printMe函数。这个是因为按钮的onClick事件处理函数仍然绑定在旧的printMe函数上。所以我们需要更新代码将其绑定到新的printMe函数上。

index.js

 ...

- document.body.appendChild(component());
+ let element = component(); // 存储 element,以在 print.js 修改时重新渲染
+ document.body.appendChild(element);

  if (module.hot) {
    module.hot.accept('./print.js', function() {
      console.log('Accepting the updated printMe module!');
-     printMe();
+     document.body.removeChild(element);
+     element = component(); // Re-render the "component" to update the click handler
+     element = component(); // 重新渲染 "component",以便更新 click 事件处理函数
+     document.body.appendChild(element);
    })
  }

console

[HMR] Waiting for update signal from WDS...
client:48 [WDS] Hot Module Replacement enabled.
client:52 [WDS] Live Reloading enabled.
print.js:2 Updateing print.js.bn.....!
2client:55 [WDS] App updated. Recompiling...
reloadApp.js:19 [WDS] App hot update...
log.js:24 [HMR] Checking for updates on the server...
index.js:21 Accepting the updated printMe module...11.!
print.js:2 Updateing print.js.b3333n.....!
log.js:24 [HMR] Updated modules:
log.js:24 [HMR]  - ./src/print.js
log.js:24 [HMR] App is up to date.

综上,我们可以根据webpack-dev-server 的hot来热加载css/js,只要在module里面配置了对应的loader就行。