我读过几页关于Webpack中的热模块替换的文章。 甚至还有一个使用它的示例应用程序。

我读了所有这些,但还是不明白。

我能用它做什么?

它是否应该只用于开发而不用于生产? 它是否像LiveReload,但你必须自己管理它? WebpackDevServer是否以某种方式与liverload集成?

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


首先,我想指出热模块替换(HMR)仍然是一个实验特性。

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

文档

Prerequirements:

使用插件:https://webpack.js.org/concepts/plugins/ 代码拆分:https://webpack.js.org/guides/code-splitting/ webpack-dev-server: https://webpack.js.org/configuration/dev-server/

这不是关于HMR的,但这里有链接:

例如:https://webpack.js.org/guides/hot-module-replacement/ API: https://webpack.js.org/concepts/hot-module-replacement/

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

它是如何工作的?

从应用程序视图

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

从编译器(webpack)视图

除了正常的资产外,编译器还需要发出“Update”以允许从以前的版本更新到这个版本。“最新情况”包括两部分:

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

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

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

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

从模块视图

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

在大多数情况下,在每个模块中编写HMR代码并不是强制性的。如果模块没有HMR处理程序,则会弹出更新。这意味着单个处理程序可以处理完整模块树的更新。如果这个树中的一个模块被更新,整个模块树将被重新加载(只是重新加载,而不是传输)。

从HMR运行时视图(技术)

为模块系统运行时发出额外的代码来跟踪模块的父模块和子模块。

在管理端,运行时支持两种方法:检查和应用。

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

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

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

现在所有无效的模块都被处置(处置处理程序)并卸载。然后更新当前散列,并调用所有“接受”处理程序。运行时切换回空闲状态,一切照常进行。

我能用它做什么?

您可以在开发中使用它作为liverload的替代品。实际上webpack-dev-server支持热模式,即在重新加载整个页面之前尝试使用HMR进行更新。你只需要添加webpack/hot/dev-server入口点,并使用——hot调用dev-server。

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

一些加载器已经生成了可热更新的模块。例:样式加载器可以交换样式表。你不需要做任何特别的事情。

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

Yes

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

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

一个模块只有在你“接受”它时才能被更新。所以你需要module。hot。accept模块在父模块或父模块的父模块。路由器是一个好地方,或者是一个子视图。

如果你只想在webpack-dev-server中使用它,只需添加webpack/hot/dev-server作为入口点。否则,您需要一些调用check和apply的HMR管理代码。

观点:是什么让它这么酷?

它是LiveReload,但对每个模块都适用。 您可以在生产中使用它。 更新尊重你的代码分割,只下载更新你的应用程序使用的部分。 您可以将它用于应用程序的一部分,并且它不会影响其他模块 如果HMR被禁用,编译器将删除所有HMR代码(将其包装在If (module.hot)中)。

警告

It's experimental and not tested so well. Expect some bugs. Theoretically usable in production, but it may be too early to use it for something serious. The module IDs need to be tracked between compilations so you need to store them (records). The optimizer cannot optimize module IDs any more after the first compilation. A bit of an impact on bundle size. HMR runtime code increases the bundle size. For production usage, additional testing is required to test the HMR handlers. This could be pretty difficult.

虽然公认的答案正确地解释了一切,但下面的描述应该有助于更快地理解HMR是什么。

本质上(概括地说!)——它通过在运行时用更改替换模块来减少页面刷新的数量,从而帮助开发。

在搜索HMR的时候,我发现了一篇解释这个概念的文章,但它太长了,所以这里有一个GIF图片,解释了这个概念,没有太多的文字。

这里它在工作-注意,计时器不会重置为0,因为它会在页面重新加载后,CSS改变自动刷新。

Webpack有助于实现HMR。你可以在这里找到文档

它有助于实现以下目标:

在重新加载期间保留应用程序状态(在没有HMR时总是丢失) 通过只更新已更改的内容来节省宝贵的开发时间。 更快地调整样式——几乎可以与在浏览器调试器中更改样式相媲美。

下面是实现HMR的webpack指南