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--hotflag, or theHotModuleReplacementPluginin 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的面试题 随着现代前端开发的复 ...
随机推荐
- 【Java并发编程】:并发新特性—Executor框架与线程池
Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...
- as和is,但is也有as所没有的功能[C#] --转载 甘木
在C#中,我们可以使用is as操作符来判断某数据类型和其它指定类型的关系 1. 用is运算符验证基础类型 C#允许在继承链中向下转型,所以如果DerivedClass派生自BaseClass,那么D ...
- MediaWIKI部署流程
1.下载mediawiki,地址:https://www.mediawiki.org/wiki/MediaWiki 2.下载xxamp集成软件,地址:https://www.apachefriends ...
- C语言初学
输出控制符 输出控制符 含义 %d int 整型数 %ld long int %c char 一个字符 %f float 浮点数,整数/整数=整数,整数/小数=小数 %lf double %x %X ...
- Maven Source Plugin
项目pom文件build下添加配置: 01 <plugin> 02 <groupId>org.apache.maven.plugins</groupId> 03 & ...
- 糗事之 -- 用ssh公钥实现免密码登录
前言:工作原因,每天都会登录好多次服务器,每次都是ssh root@192.168..... 然后输入密码,来来回回输几次真是很烦啊. 问题:怎么可以在每次ssh连接服务器时不用输入密码,直接登录? ...
- ES6 笔记(二)- 总结
在最近进行的项目中,已经全面使用到ES6,这里对ES6进行整理总结.用得比较多的是带*的内容,这些语法.新增类型.模块调用等从代码量上.可读性上.操作上给项目带来了不少便利. 1.语法 1 ...
- [转]一步步学习EF Core(2.事务与日志)
本文转自:http://www.cnblogs.com/GuZhenYin/p/6862505.html 上节我们留了一个问题,为什么EF Core中,我们加载班级,数据并不会出来 其实答案很简单,~ ...
- sql中的分页实现
1.两种方式 1.1:row_number() over()函数 1.2:OFFSET ....FETCH OFFSET { integer_constant | offset_row_count_e ...
- debian上安装docker ce
在Debian9上安装Docker CE 使用从包中安装的方式 Docker是一个开源的容器引擎,它有助于更快地交付产品.Docker可将应用程序和基础设施层隔离,并且将基础设施当作程序一样进行管理. ...