我正在学习Webpack,偶然发现了这篇文章。我大致了解什么是热模块更换(HMR)。我可以通过以下示例代码配置webpack HMR插件:
var plugins = [ new webpack.HotModuleReplacementPlugin(), // using HMR plugin
new HtmlWebpackPlugin({template: './index.html'})
];
module.exports = {
// webpack config object
context: entryBasePath,
entry:{
app: ['webpack/hot/dev-server', './bootstrap.js']
},
output: {
path: outputBasePath,
filename: './bundle.js',
sourceMapFilename: '[file].map' // set source map output name rule
},
devtool: 'source-map', // enable source map
plugins: plugins,
module: {
loaders: [
{ test: /.scss$/, loader: 'style!css!sass'},
{ test: /.tpl$/, loader: 'raw' },
{
test: /.woff2?(?v=[0-9].[0-9].[0-9])?$/,
loader: 'url?limit=10000'
},
{
test: /.(ttf|eot|svg)(?[sS]+)?$/,
loader: 'file'
},
{ test: /bootstrap-sass/assets/javascripts//, loader: 'imports?jQuery=jquery' }
]
}
}
我的问题是,这篇文章试图从什么方面解释Webpack热模块更换?我在哪里可以使用该页面上提供的示例代码?
简而言之,我的问题是这到底是关于什么的?
热模块更换(HMR)是在应用程序运行时交换代码的一项功能。它允许您在保留应用程序状态的同时编辑代码。这对于样式设置特别有用,因为您通常只想在不重新加载浏览器的情况下更新样式。
然而,只有当代码提供特殊的钩子来删除以前的代码、撤消所有副作用并注入新代码时,这才有可能。典型的副作用:注册事件侦听器、将数据存储在对象中、修改全局状态。
例如,在应用程序运行时替换CSS是一项简单的任务,因为CSS在每个定义中都没有副作用。为了理解HMR的内部结构,让我们来看看样式加载器:
样式加载器附加了这个特殊的代码来处理HMR(我已经删除了一些对这个例子不重要的代码):
if (module.hot) {
// When the styles change, update the <style> tags
module.hot.accept(loaderUtils.stringifyRequest(this, !!remainingRequest), function () {
var newContent = require(loaderUtils.stringifyRequest(this, !!remainingRequest));
update(newContent);
});
// When the module is disposed, remove the <style> tags
module.hot.dispose(function () {
update();
});
}
if (module.hot) {
检查,如果HMR已启用module.hot.accept(<module identifier>, handler)
注册一个处理程序以注入新代码module.hot.dispose(handler)
注册一个处理程序来处理旧代码
update
函数很难读取,但它基本上只是向document.head
添加新的样式表并删除未使用的样式表。
React中的HMR有点复杂,在过去的几个月里经历了一些严重的重构。但基本原理是,每个导出的组件都封装在一个代理中。代理是一个与另一个对象类似的对象。这可以通过将所有函数转发到"真实"对象来实现,也可以通过使用ES2015代理(显然功能要强大得多)来实现。这样,可以很容易地交换原始对象,而无需更新任何其他组件。我在另一个SO回答中对此进行了更详细的描述。
为了使HMR发挥作用,需要满足以下一些要求:
您的代码需要
module.hot.accept
和module.hot.dispose
的挂钩来处理代码更新。这通常是通过加载器(例如,样式加载器)或babel转换(例如,babel预置react hmre预置)来实现的。从技术上讲,您也可以在每个模块中为自己编写这些挂钩。。。也许这是开始了解内部情况的好方法。如果更新后的模块不包含此代码或无法处理更新,则更新将被拒绝,webpack将重新加载浏览器窗口。这可能看起来像HMR,但实际上只是浏览器刷新。您需要客户端和服务器上的一些基础设施来建立WebSockets连接,向客户端推送新代码,并通知所有过时的模块来处理更新。实现这一点最简单的方法是使用带有
webpack-dev-server --hot --inline
的webpack-dev服务器。不需要其他代码。特别是不要在webpack.config.js
中添加HMR插件或任何webpack开发服务器的东西——它都将通过--hot --inline
启用。有更多的方法可以配置它——根据您的设置,这可能是实际需要的。这就是为什么这一部分对于新手来说常常如此令人困惑的原因。Webpack需要在监视模式下运行,因为我们只想处理更改的文件。当您使用
webpack-dev-server
或webpack-dev-middleware
时,您不需要在配置中添加任何内容,它已经将webpack编译器置于监视模式(当然,只有在lazy: false
的情况下)。