本文针对热模块更换的哪些方面?
Posted
技术标签:
【中文标题】本文针对热模块更换的哪些方面?【英文标题】:What aspect of Hot Module Replacement is this article for? 【发布时间】:2016-08-29 05:44:51 【问题描述】:我正在学习 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 热模块替换?我在哪里可以使用该页面上提供的示例代码?
简而言之,我的问题是this 到底是什么?
【问题讨论】:
【参考方案1】:热模块替换 (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 将重新加载浏览器窗口。这可能看起来像 HMR,但实际上只是浏览器刷新。
您需要客户端和服务器上的一些基础设施来建立 WebSockets 连接,将新代码推送到客户端并通知所有过时的模块来处理更新。实现这一点的最简单方法是使用带有webpack-dev-server --hot --inline
的 webpack-dev-server。不需要其他代码。特别是不要将 HMR 插件或任何 webpack-dev-server 的东西添加到 webpack.config.js
中——它们都将通过 --hot --inline
启用。有更多的方法来配置它——这实际上可能是需要的,具体取决于您的设置。这就是为什么这部分经常让新手感到困惑的原因。
Webpack 需要在监视模式下运行,因为我们只想处理更改的文件。当您使用webpack-dev-server
或webpack-dev-middleware
时,您不需要在配置中添加任何内容,它已经放置了webpack compiler into watch-mode(当然,仅在lazy: false
的情况下)。
【讨论】:
我注意到webpack-dev-server --hot --inline
,即使我省略了 --hot
,HMR 仍然有效。你能帮我理解为什么吗?
您的webpack.config.js
中是否也应用了HMR 插件。您应该添加插件并使用--hot
调用它以上是关于本文针对热模块更换的哪些方面?的主要内容,如果未能解决你的问题,请参考以下文章