我正在学习Webpack并遇到this article。 我对什么是热模块替换(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)(\?[\s\S]+)?$/,
loader: 'file'
},
{ test: /bootstrap-sass\/assets\/javascripts\//, loader: 'imports?jQuery=jquery' }
]
}
}
我的问题是this article的哪个方面试图解释有关Webpack Hot Module Replacement的问题?我在哪里可以使用该页面上提供的示例代码?
简而言之,我的问题是(地狱)this是什么?
答案 0 :(得分:7)
热模块更换(HMR)是在应用程序运行时交换代码的功能。它允许您在保留应用程序状态的同时编辑代码。这对样式特别有用,您通常只想在不重新加载浏览器的情况下更新样式。
但是,只有在代码提供了特殊的钩子来删除前面的代码,撤消所有副作用并注入新代码时,才能实现这一点。典型的副作用:注册事件监听器,将数据存储在对象中,修改全局状态。
例如,在应用程序运行时替换CSS是一项简单的任务,因为CSS根据定义是无副作用的。为了理解HMR的内部结构,我们来看看style-loader:
样式加载器附加this special code来处理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
function很难阅读,但它基本上只是将新的样式表添加到document.head
并删除未使用的样式表。
React中的HMR有点复杂,并且在过去几个月中经历了一些严重的重构。但基本原则是每个导出的组件都包含在代理中。代理是一个像另一个对象一样的对象。这可以通过将所有函数转发到“真实”对象或使用ES2015 proxies(显然更强大)来实现。这样,可以轻松地换出原始对象而无需更新任何其他组件。我在another SO answer中详细描述了这一点。
为了使HMR有效,需要满足一些要求:
您的代码需要module.hot.accept
和module.hot.dispose
的挂钩来处理代码更新。这通常通过加载器(例如,样式加载器)或babel转换(例如,babel-preset-react-hmre预设)来实现。从技术上讲,你可以也为自己在每个模块中编写这些钩子......也许这是开始学习内部的好方法。如果更新的模块不包含此代码或无法处理更新,则更新将被拒绝,webpack将重新加载浏览器窗口。这可能看起来像,但实际上只是浏览器刷新。
您需要客户端和服务器上的某些基础结构来建立WebSockets连接,将新代码推送到客户端并通知所有过时的模块来处理更新。实现此目的的最简单方法是将webpack-dev-server与webpack-dev-server --hot --inline
一起使用。不需要其他代码。特别是不要将{HMR插件或任何webpack-dev-server内容添加到webpack.config.js
- 它将全部通过--hot --inline
启用。有更多方法可以配置 - 根据您的设置,实际上可能需要这些方法。这通常是为什么这部分经常让新人感到困惑的原因。
Webpack需要在监视模式下运行,因为我们只想处理更改的文件。当您使用webpack-dev-server
或webpack-dev-middleware
时,您无需向配置中添加任何内容,它已放置webpack compiler into watch-mode(仅限lazy: false
的情况,当然)。