webpack HMR是如何工作的?
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 theHotModuleReplacementPlugin
in yourwebpack.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是如何工作的?的更多相关文章
- webpack hmr
参考: https://webpack.js.org/concepts/hot-module-replacement/ https://webpack.js.org/guides/hot-module ...
- webpack HMR原理
在启动 devServer 的时候,sockjs 在服务端和浏览器端建立了一个 webSocket 长连接,以便将 webpack 编译和打包的各个阶段状态告知浏览器,最关键的步骤还是 webpack ...
- 细说前端自动化打包工具--webpack
背景 记得2004年的时候,互联网开发就是做网页,那时也没有前端和后端的区分,有时一个网站就是一些纯静态的html,通过链接组织在一起.用过Dreamweaver的都知道,做网页就像用word编辑文档 ...
- webpack 4.0.0-beta.0 新特性介绍
webpack 可以看做是模块打包机.它做的事情是:分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式 ...
- Webpack & The Hot Module Replacement热模块替换原理解析
Webpack & The Hot Module Replacement热模块替换原理解析 The Hot Module Replacement(HMR)俗称热模块替换.主要用来当代码产生变化 ...
- webpack的热更新
webpack的热更新是如何做到的?说明其原理? webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR. 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉 ...
- 关于webpack的面试题
随着现代前端开发的复杂度和规模越来越庞大,已经不能抛开工程化来独立开发了,如react的jsx代码必须编译后才能在浏览器中使用:又如sass和less的代码浏览器也是不支持的. 而如果摒弃了这些开发框 ...
- webpack系列--浅析webpack的原理
一.前言 现在随着前端开发的复杂度和规模越来越大,鹰不能抛开工程化来独立开发,比如:react的jsx代码必须编译后才能在浏览器中使用,比如sass和less代码浏览器是不支持的.如果摒弃这些开发框架 ...
- 25、前端知识点--webpack篇之面试考点
前端面试之webpack篇 https://blog.csdn.net/sinat_17775997/article/details/78122999 关于webpack的面试题 随着现代前端开发的复 ...
随机推荐
- 我与GitHub的第一次——自制音乐文件修改器
背景: 随机播放,所有的音乐播放器里面现在几乎都有这个功能吧.但是有没有发现,自己的播放器在选择随机播放的时候,经常会听到重复顺序的歌曲呢?反正我是有这样的感觉,无耐自己平时下的歌曲都是“歌手名—歌曲 ...
- winrar 命令行 解压文件
1,最简单的压缩命令:winrar a asdf.txt.rar asdf.txt a的意思是进行压缩动作,后面第一个参数是被压缩后的文件名,后缀当然是rar了,最后面 的参数就是要被压缩的文件名 2 ...
- 前端通信:ajax设计方案(二)---集成轮询技术
上一篇文章介绍了ajax技术核心方法,和跨域的问题(只要后台支持跨域默认post就可以),这篇文章讲解一下使用ajax实现的轮询技术,至于iframe,SSE服务器单向推送,以及webSocket双工 ...
- 修改salt-minion的id后报错解决方法
centos7使用命令 /usr/bin/salt-minion start运行报错 Error parsing configuration file: /etc/salt/master - expe ...
- Jav实现F(n)=F(n-1)+F(n-2)+.....+F(1)+1
private static int func(int count) { // TODO Auto-generated method stub int cou = 0; if(count==1) ...
- 面试题21:如何判断二叉树是搜索二叉树BST?
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- select样式
select设置了宽高: 样式是这样的: 如果在select的标签内部加入size="2" size的值只要大于1,select的设置大小会起作用 样式是这样的: 3.点击中 ...
- Extjs报错处理
错误信息: IE:SCRIPT1009: 缺少 '}' FF: SyntaxError: identifier starts immediately after numeric literal ... ...
- 微信小程序登录方案
微信小程序登录方案 登录程序 app.js 调用wx.login获取code 将code作为参数请求自己业务登录接口获取session_key 存储session_key 如果有回调执行回调 App( ...
- 【转】Visio绘制WEB流程图的心得
一个哥们在MSN上告诉我,他们公司的交互设计师只产出流程图,并问我用什么标准评价流程图的好坏.他的说法把我彻底震了-这分工也太细了吧!也不知道该说他们那里这样是好还是不好. 不过仔细想来,我倒的确没有 ...