这篇文章针对的是热模块更换的哪些方面



我正在学习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.acceptmodule.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-serverwebpack-dev-middleware时,您不需要在配置中添加任何内容,它已经将webpack编译器置于监视模式(当然,只有在lazy: false的情况下)。

最新更新