https://github.com/webpack/docs/wiki/hot-module-replacement-with-webpack

https://www.jianshu.com/p/941bfaf13be1

什么是HMR?

Hot Module Replacement(HMR)在web应用正在运行时在无需整个页面refresh的前提下,实现对特定模块替换,添加,或者删除的操作。

HMR是如何工作的?

webpack会在构建过程中向bundle中添加一小段HMR Runtime代码,这段HMR Runtime将在你的app中运行。当构建结束时,webpack并不会退出,而是在那里监听源代码的任何改变。如果webpack检测到代码的变化,它只对变更过的module执行rebuild。依赖于webpack的配置,要么webpack自己向HRM runtime程序发送一个信号,或者HMR Runtime主动向webpack征询代码变化。无论任何一种模式下,变更过的module将被发往HMR runtime.而这个runtime代码将试图应用这个hot update.首先runtime检查被更新的module是否能够accept这个hot update.如果不能,则runtime继续检查required这个update module的module是否能够accept.如果还不能accept,则继续bubble up往上冒泡,直到找到能够accept的module,或者直到app entry point.而这种情况下,hot update将会fail掉。

从app来看

app代码请求HRM runtime执行检查Update的工作。HMR Runtime下载这个update(async)并且告知app code有一个update已经ready. app代码请求HRM Runtime来apply 这个update. HMR runtime应用上这个update(sync). app代码可能会也可能不会需要用户的交互(这个你自己决定)

从compiler(webpack)来看

除了普通的assets, compiler需要发射"update"事件以便运行系统更新这个update到新的版本。"update"包含两部分内容:

1. the update manifest(json)

2. one or multiple update chunks(js)

manifest包含新的compilation hash和一个所有的updated chunks列表清单;

而update chunks则包含了所有的updated module的代码(或一个flag如果该模块被删除掉的话)

compiler也会确保module和chunk id在这些build之间保持一致性。它使用一个records.json文件来保存这些信息以便保持一致和同步。

从module的角度来看

HMR是一个可选打开的功能,所以HMR仅仅会影响到那些包含HMR Code的模块。总的来说,module developer需要写handlers代码,如果该模块的dependency更新了的话,这个Handlers代码将被调用以便接收这个update。他们也可以写一个handler,当该module本身而不是其dependency更新时调用他。

在大多数情况下,并不需要在每个module中都写HRM code。如果一个module没有HMR handler那么这个update将会bubble up.这意味着仅需一个handler就可以处理这个模块的依赖树上的所有module update。如果该依赖树中的任何单个模块做了更新,那么整个module tree就将得到reloaded(only reloaded not transferred)

从HMR runtime的角度来看

HMR runtime是一段额外的代码注入用于跟踪module parents和module children.

从管理的角度说,这个runtime支持两个方法: check和apply

一个check执行http请求,请求manifest列表文件。如果这个请求失败了,将不会有任何update执行。否则,新的updated chunks将和当前已经加载过的chunks进行比较。针对每个已经loaded的chnks,如果有update,则将下载对应的update chunk.所有的模块更新在runtime看来都作为update来缓存。runtime切换到ready状态,意味着一个update已经下载并且可以用于applied.

对每一个new chunk(无loaded chunk对应),update chunk也需要下载。

apply方法标志所有updated modules为invalid状态。针对每一个invalid module,需要有一个update handler在本模块里或者其父亲模块里存在。否则这个Invalid module状态会bundle up并且设置其所有的父亲组件为invalid.这个流程将一直进行下去直到没有"bubbling up"可以发生为止。如果冒泡到了entry point,则这个process将fail掉。

现在所有invlaid modules将被disposed(处置掉,需要dispose handler)并且卸载掉。然后当前hash更新并且所有"accept" handlers将被调用。runtime最后会切换到idle状态,继续下一轮。

我们能做些什么?

你可以作为LiveReload的替代品将HMR应用在dev过程中。实际上,webpack-dev-server实际上会在执行重新加载整个页面前试图使用HMR来完成热更新。你只需要将webpack/hot/dev-server本身加到你的webpack build的entry point中去,并且在命令行加上--hot参数即可。

webpack/hot/dev-server将在HMR update失败后重新加载整个页面。如果你希望自己来执行reload page动作,你可以增加webpack/hot/only-dev-server到entry point中,而不是dev-server。

你也可以将它用在生产环境下作为一种更新的机制存在。这时,你需要写自己的管理代码以便集成HRM到你的app中。

有一些loaders已经具有了产生hot-updateable module的能力,比如style-loader就可以swap stylesheet.在这种情况下,你无需做任何事情。

需要什么方可使用HMR呢?

一个module只有你"accpet",才能实现HMR updated。所以,你需要"module.hot.accept"存在于你的模块或模块的父亲链中。比如,一个router或者一个subview将是一个实现accept的好地方。

如果你仅仅希望和webpack-dev-server集成使用HMR而不是自己来写代码,你可以增加webpack/hot/dev-server作为一个entry point, 否则,你需要写一些HMR management code来调用check和apply.

你需要在compiler中enable records以便在不同的进程间跟踪module id.(watch mode和webpack-dev-server保存这些records在内存中,所以你开发时无需)

你需要在compiler中enable HMR,以便webpack向bundle中加入HMR runtime.

为什么HMR这么cool?

它就像这对每个module实现了liveReload一样,而不是针对页面来做liveReload

你可以在生产环境中使用它;

updates也会尊重code splitting,只会下载你的app变更部分

你可以仅在应用的部分中应用,而不会影响其他的模块。

如果HMR disabled,那么所有的HMR code都将被webpack清除掉(wrap it in "

if(module.hot)

中,以便能被webpack轻松剔除

")

Tutorial

To use hot code replacement with webpack you need four things:

  • records (--records-path, recordsPath: ...)
  • globally enable hot code replacement (HotModuleReplacementPlugin)
  • hot replacement code in your code module.hot.accept
  • hot replacement management code in your code module.hot.check, module.hot.apply

A small testcase:

/* style.css */
body {
background: red;
}
/* entry.js */
require("./style.css");
document.write("<input type='text' />");

That's enough to use hot code replacement with the dev-server.

npm install webpack webpack-dev-server -g
npm install webpack css-loader style-loader
webpack-dev-server ./entry --hot --inline --module-bind "css=style\!css"

The dev server provides in memory records, which is good for development.

The --hot switch enables hot code replacement.

This adds the HotModuleReplacementPlugin. Make sure to use either the --hot flag, or the HotModuleReplacementPlugin in your webpack.config.js, but never both at the same time as in that case, the HMR plugin will actually be added twice, breaking the setup.

There is special management code for the dev-server at webpack/hot/dev-server, which is automatically added by --inline. (You don't have to add it to your webpack.config.js)

The style-loader already includes hot replacement code.

If you visit http://localhost:8080/bundle you should see the page with a red background and a input box. Type some text into the input box and edit style.css to have another background color.

Voilà... The background updates but without full page refresh. Text and selection in the input box should stay.

Read more about how to write you own hot replacement (management) code: hot module replacement

Check the example-app for a demo without coding. (Note: It's a bit old, so don't look at the source code, because the HMR API changed a bit in between)

webpack HMR是如何工作的?的更多相关文章

  1. webpack hmr

    参考: https://webpack.js.org/concepts/hot-module-replacement/ https://webpack.js.org/guides/hot-module ...

  2. webpack HMR原理

    在启动 devServer 的时候,sockjs 在服务端和浏览器端建立了一个 webSocket 长连接,以便将 webpack 编译和打包的各个阶段状态告知浏览器,最关键的步骤还是 webpack ...

  3. 细说前端自动化打包工具--webpack

    背景 记得2004年的时候,互联网开发就是做网页,那时也没有前端和后端的区分,有时一个网站就是一些纯静态的html,通过链接组织在一起.用过Dreamweaver的都知道,做网页就像用word编辑文档 ...

  4. webpack 4.0.0-beta.0 新特性介绍

    webpack 可以看做是模块打包机.它做的事情是:分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式 ...

  5. Webpack & The Hot Module Replacement热模块替换原理解析

    Webpack & The Hot Module Replacement热模块替换原理解析 The Hot Module Replacement(HMR)俗称热模块替换.主要用来当代码产生变化 ...

  6. webpack的热更新

    webpack的热更新是如何做到的?说明其原理? webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR. 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉 ...

  7. 关于webpack的面试题

    随着现代前端开发的复杂度和规模越来越庞大,已经不能抛开工程化来独立开发了,如react的jsx代码必须编译后才能在浏览器中使用:又如sass和less的代码浏览器也是不支持的. 而如果摒弃了这些开发框 ...

  8. webpack系列--浅析webpack的原理

    一.前言 现在随着前端开发的复杂度和规模越来越大,鹰不能抛开工程化来独立开发,比如:react的jsx代码必须编译后才能在浏览器中使用,比如sass和less代码浏览器是不支持的.如果摒弃这些开发框架 ...

  9. 25、前端知识点--webpack篇之面试考点

    前端面试之webpack篇 https://blog.csdn.net/sinat_17775997/article/details/78122999 关于webpack的面试题 随着现代前端开发的复 ...

随机推荐

  1. 正则表达式最后的/i是不区分大小写的意思

    eg: "/\/*install$/i" 正则表达式 代表什么意思   /表达式的内容/ ,php中的正则表达式都必须在 / / 内 \/是匹配"/" 号,*号 ...

  2. 在Java Web项目中,不用ActionContext类来获得tomcat部署项目的绝对路径

    例子:sendIosApns.class.getClassLoader().getResource("").getFile().replaceAll("%20" ...

  3. MySQL中You can't specify target table for update in FROM clause异常

    mysql中You can't specify target table <tbl> for update in FROM clause错误的意思是说,不能先select出同一表中的某些值 ...

  4. Java 获取汉字串首字母并大写和获取汉字的全拼,英文字符不变

    在开发中我们难免会遇到需要提出汉字中的拼音的首字母.提出汉字的拼音,接着便介绍一个工具类 pinyin4j.jar,首先需要下载 jar 包. Pinyin4j是一个功能强悍的汉语拼音工具包,是sou ...

  5. Node.js之Express二

    好久没写了,今天看博客,觉得有必要把node.js继续写完,善始善终.原本想着把小崔课堂继续讲下去,由于其他原因也就此耽搁下来,看看以后还有没有机会吧.废话不扯,123开始. 一.Exoress之Re ...

  6. [转] Linux Crontab 定时任务 命令详解

    一.  Crontab 介绍 crontab命令的功能是在一定的时间间隔调度一些命令的执行. 1.1 /etc/crontab 文件 在/etc目录下有一个crontab文件,这里存放有系统运行的一些 ...

  7. ado.net中事务的使用

    ADO.Net中也提供了事务处理功能,通过ADO.net事务,可以将多个任务绑定在一起,如果所有的任务成功,就提交事务,如果有一个任务失败,就讲滚回事务 执行ADO.Net事务包含四个步骤,接下来以S ...

  8. WPF 从文件加载字体

    本文告诉大家从文件加载字体.在wpf 使用 fontfamily 显示指定的 ttf 显示字体 假如有字体在 C:\Projects\MyProj\free3of9.ttf ,可以使用 Private ...

  9. Walkway.js – 创建简约的 SVG 线条动画

    Walkway.js 是一个使用线条和路径元素组成 SVG 动画图像的简单方法.只需根据提供的配置对象创建一个新的 Walkway 实例就可以了.这种效果特别适合那些崇尚简约设计风格的网页.目前, W ...

  10. drawRect:和layoutSubview的区别

    关于这两个方法的区别 还是有点意思的. UIView的setNeedsDisplay和setNeedsLayout方法.首先两个方法都是异步执行的.setNeedsDisplay会调用自动调用draw ...