【问题标题】:What exactly is Hot Module Replacement in Webpack?Webpack 中的热模块替换到底是什么?
【发布时间】:2015-11-09 13:29:17
【问题描述】:

我读过 few pages 关于 Webpack 中的热模块替换。
甚至还有一个sample app 那个uses it

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

我能用它做什么?

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

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

【问题讨论】:

标签: javascript module livereload webpack


【解决方案1】:

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

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

文档

先决条件:

对于 HMR 来说不是很多,但这里是链接:

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

它是如何工作的?

从应用视图

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

从编译器(webpack)视图

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

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

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

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

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

从模块视图

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

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

从 HMR 运行时视图(技术)

为模块系统运行时发出额外代码以跟踪模块parentschildren

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

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

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

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

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

我能用它做什么?

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

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

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

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

是的

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

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

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

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

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

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

注意事项

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

【讨论】:

  • 一个地狱般的答案。
  • 再次感谢您的解释,我 made a video 展示了 HMR 实时编辑 React 应用程序的能力。
  • 相当酷...我想过制作一个反应加载器,它添加 HMR 和异步加载到反应组件。
  • 当您将 require 包装在 try-catch 块中的 HMR 更新处理程序中时,您可以捕获更新模块中的错误。
【解决方案2】:

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

基本上(简而言之!) - 它通过在运行时用更改替换模块来减少页面刷新次数来帮助开发。

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

它在起作用——请注意,计时器不会像页面重新加载后那样重置为 0,而且 CSS 也会更改自动刷新。

Webpack 有助于实现 HMR。你可以找到文档here

有助于实现以下目标:

  • 在重新加载期间保留应用程序状态(如果没有 HMR,它总是会丢失)

  • 仅更新已更改的内容,从而节省宝贵的开发时间。

  • 更快地调整样式 - 几乎可以与在浏览器的调试器中更改样式相媲美。

Here是实现HMR的webpack指南

【讨论】:

  • 多么棒的,简单直接的答案,礼物更好地解释了 1000 字
猜你喜欢
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 2017-06-20
  • 2017-02-27
  • 1970-01-01
  • 2017-06-28
  • 2022-07-01
相关资源
最近更新 更多