Webpack中的热模块更换到底是什么?


245

我读了 有关的WebPack热模块的更换。
甚至还有一个示例应用程序使用它

我已经阅读了所有这些内容,但仍然不明白。

我该怎么办?

  1. 是否应该仅将其用于开发而非生产中?
  2. 就像LiveReload,但您必须自己管理它吗?
  3. WebpackDevServer是否以某种方式与LiveReload集成?

假设我想在将CSS和JS模块保存到磁盘时更新它们(一个样式表)和JS模块,而无需重新加载页面并且不使用LiveReload之类的插件。这是热模块更换可以帮助我的吗?我需要做什么工作?HMR已经提供了什么?


HMR用的WebPack是几乎一样好这样的:medium.com/@the1mills/...
亚历山大米尔斯

Answers:


406

首先,我想指出的是,热模块更换(HMR)仍是一项实验功能。

HMR是在运行的应用程序中交换模块(以及添加/删除模块)的一种方式。您基本上可以更新已更改的模块,而无需重新加载整个页面。

文献资料

前提条件:

对于HMR来说,它不算什么,但是这里是链接:

我将这些答案添加到文档中。

它是如何工作的?

从应用程序视图

该应用程序代码要求HMR运行时检查更新。HMR运行时下载更新(异步),并告知应用程序代码可用更新。该应用程序代码要求HMR运行时应用更新。HMR运行时将应用更新(同步)。应用程序代码在此过程中可能会或可能不需要用户交互(由您决定)。

从编译器(webpack)视图

除了常规资产外,编译器还需要发出“更新”以允许从以前的版本更新到该版本。“更新”包含两个部分:

  1. 更新清单(json)
  2. 一个或多个更新块(js)

清单包含新的编译哈希和所有更新块的列表(2)。

更新块包含该块中所有已更新模块的代码(如果删除了模块,则包含一个标志)。

编译器还确保这些构建之间的模块ID和块ID一致。它使用“ records” json文件在构建之间存储它们(或将它们存储在内存中)。

从模块视图

HMR是一项可选功能,因此它仅影响包含HMR代码的模块。该文档描述了模块中可用的API。通常,模块开发人员编写在更新此模块的依赖项时调用的处理程序。他们还可以编写一个在更新此模块时调用的处理程序。

在大多数情况下,并非必须在每个模块中都编写HMR代码。如果模块没有HMR处理程序,则更新冒泡。这意味着单个处理程序可以处理整个模块树的更新。如果更新了该树中的单个模块,则将重新加载完整的模块树(仅重新加载,不传输)。

从HMR运行时视图(技术)

为模块系统运行时发出了附加代码,以跟踪模块parentschildren

在管理方面,运行时支持两种方法:checkapply

check做一个HTTP请求到更新清单。当此请求失败时,将没有可用的更新。否则,将更新的块的列表与当前加载的块的列表进行比较。对于每个加载的块,将下载相应的更新块。所有模块更新都作为更新存储在运行时中。运行时切换到ready状态,这意味着已下载更新并准备应用。

对于处于就绪状态的每个新块请求,还将下载更新块。

apply方法将所有更新的模块标记为无效。对于每个无效模块,模块中都必须有一个更新处理程序,或者每个父级中都需要有更新处理程序。否则无效者冒出来,并将所有父母也都标记为无效者。这个过程一直持续到不再发生“气泡”为止。如果气泡达到入口点,则该过程失败。

现在,所有无效模块都将被处置(处置处理程序)并卸载。然后,更新当前哈希并调用所有“接受”处理程序。运行时切换回该idle状态,一切正常进行。

生成的更新块

我该怎么办?

您可以在开发中将其用作LiveReload的替代品。实际上,webpack-dev-server支持一种热模式,该模式在尝试重新加载整个页面之前尝试使用HMR更新。您只需要添加webpack/hot/dev-server入口点并使用调用dev-server --hot

您也可以在生产中使用它作为更新机制。在这里,您需要编写自己的管理代码,以将HMR与您的应用程序集成在一起。

一些加载程序已经生成了可热更新的模块。例如style-loader可以交换样式表。您不需要做任何特别的事情。

假设我想在将CSS和JS模块保存到磁盘时更新它们(一个样式表)和JS模块,而无需重新加载页面并且不使用LiveReload之类的插件。这是热模块更换可以帮助我的吗?

我需要做什么工作?HMR已经提供了什么?

这是一个小例子:https : //webpack.js.org/guides/hot-module-replacement/

如果您“接受”模块,则只能对其进行更新。因此,您需要module.hot.accept在父母或父母的父母中使用该模块……例如,路由器是一个好地方或一个子视图。

如果只想将其与webpack-dev-server一起使用,则只需添加webpack/hot/dev-server作为入口点即可。否则,您需要一些调用check和的HMR管理代码apply

意见:是什么让它如此酷?

  • 这是LiveReload,但适用于每种模块。
  • 您可以在生产中使用它。
  • 这些更新符合您的代码拆分功能,并且仅下载应用程序使用部分的更新。
  • 您可以将其用于应用程序的一部分,并且不会影响其他模块
  • 如果禁用了HMR,则编译器将删除所有HMR代码(将其包装在中if(module.hot))。

注意事项

  • 这是实验性的,没有经过很好的测试。
  • 期待一些错误。
  • 从理论上讲可以在生产中使用,但是将它用于严肃的事情可能还为时过早。
  • 在编译之间需要跟踪模块ID,因此您需要存储它们(records)。
  • 第一次编译后,优化器无法再优化模块ID。对捆绑包大小的影响。
  • HMR运行时代码增加了包的大小。
  • 对于生产用途,需要额外的测试来测试HMR处理程序。这可能非常困难。

145
一个答案的地狱。
Dan Abramov

13
再次感谢您的解释,我制作了一个视频,展示了HMR实时编辑React应用程序的功能。
Dan Abramov 2014年

1
太酷了……我想到了制作一个React loader,它添加了HMR和异步加载来对组件进行响应。
Tobias K.


2
require将HMR更新处理程序包装在try-catch块中时,可以捕获更新的模块中的错误。
Tobias K.

10

无论如何,接受的答案将说明所有正确的内容,以下说明有助于快速了解什么是HMR。

热模块替换是javascript开发中的最新技术之一,吸引了开发人员的注意。它通过在运行时更改模块来减少页面刷新次数,从而有助于开发。

在搜索HMR时,我发现了一篇文章,解释了Internet上的概念,您可以从这里获得它,并添加一个无需过多解释即可解释该概念的GIF图像。

它在这里工作-请注意,计时器不会像重新加载页面后那样重置为0,并且CSS也更改为自动刷新。 热模块更换GIF

Webpack帮助实现HMR。您可以找到文件这里

它有助于实现关注

  • 保留在完全重载期间丢失的应用程序状态。

  • 仅通过更新更改来节省宝贵的开发时间。

  • 调整样式的速度更快-几乎可以与浏览器调试器中样式的更改相提并论。

是实现HMR的Webpack指南

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.