We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在web开发中,webpack的hot module replacement(HMR)功能是可以向运行状态的应用程序定向的注入并更新已经改变的modules。它的出现可以避免像LiveReload那样,任意文件的改变而刷新整个页面。
这个特性可以极大的提升开发拥有运行状态,以及资源文件普遍过多的前端应用型网站的效率。完整介绍可以看官网文档
本文是先从使用者的角度去介绍这个功能,然后从设计者的角度去分析并拆分需要实现的功能和实现的一些细节。
对于使用者来说,体验到这个功能需要以下的配置。
webpack.config.js:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); module.exports = { entry: { app: './src/index.js' }, devServer: { contentBase: './dist', hot: true, }, plugins: [ new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin() ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
代码: index.js 依赖print.js,使用module.hot.accept接受print.js的更新:
import './print'; if (module.hot) { module.hot.accept('./print', function () { console.log('i am updated'); }) }
改变print.js代码:
console.log('print2') console.log('i am change');
此时服务端向浏览器发送socket信息,浏览器收到消息后,开始下载以hash为名字的下载的json,jsonp文件,如下图:
浏览器会下载对应的hot-update.js,并注入运行时的应用中:
webpackHotUpdate(0,{ /***/ 30: /***/ (function(module, exports) { console.log('print2') console.log('i am change'); /***/ }) })
0 代表着所属的chunkid,30代表着所属的moduleid。
替换完之后,执行module.hot.accept的回调函数,如下图:
简单来讲,开启了hmr功能之后,处于accepted状态的module的改动将会以jsonp的形式定向的注入到应用程序中。
一张图来表示HMR的整体流程:
当翻开bundle.js的时候,你会发现Runtime代码多了许多以下的代码:
/******/ function hotDownloadUpdateChunk(chunkId) { /******/ ... /******/ } /******/ function hotDownloadManifest(requestTimeout) { /******/ ... /******/ } /****** /******/ function hotSetStatus(newStatus) { /******/ ... /******/ } /******/
打包的时候,明明只引用了4个文件,但是整个打包文件却有30个modules之多:
/* 30 */ /***/ (function(module, exports) { console.log('print3') console.log('i am change'); /***/ })
到现在你可能会有以下几个疑问:
以上问题,可以从三个不同的角度去解决。server,webpack,brower。
entry:{app:'./src/index.js'}
,转换为
entry:{app:['/Users/zhujian/Documents/workspace/webpack/webpack-demos-master/node_modules/_webpack-dev-server@2.11.2@webpack-dev-server/client/index.js?http://localhost:8082'],'webpack/hot/dev-server','./src/index.js'}
构建业务代码时,附带上socketjs,hot代码。
Server.js
if (this.hot) this.sockWrite([conn], 'hot');
浏览器
hot: function hot() { _hot = true; log.info('[WDS] Hot Module Replacement enabled.'); }
监听编译器的生命周期模块。
compiler.plugin('compile', invalidPlugin); compiler.plugin('invalid', invalidPlugin); compiler.plugin('done', (stats) => { this._sendStats(this.sockets, stats.toJson(clientStats)); this._stats = stats; });
context.compiler.plugin("done", share.compilerDone); context.compiler.plugin("invalid", share.compilerInvalid); context.compiler.plugin("watch-run", share.compilerInvalid); context.compiler.plugin("run", share.compilerInvalid);
MainTemplate增加module-obj,module-require事件
module-obj事件负责生成以下代码
/******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {}, /******/ hot: hotCreateModule(moduleId), /******/ parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp), /******/ children: [] /******/ }; /******/
module-require事件负责生成以下代码
/******/ modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
新增Watching类支持watch模式,并结合watchpack监听文件变化。
class Watching { .... }
新增updateHash实现
updateHash(hash) { this.updateHashWithSource(hash); this.updateHashWithMeta(hash); super.updateHash(hash); }
updateHash(hash) { hash.update(`${this.id} `); hash.update(this.ids ? this.ids.join(",") : ""); hash.update(`${this.name || ""} `); this._modules.forEach(m => m.updateHash(hash)); }
增加createHash方法,默认调用md5计算compilation hash。调用依赖树module,chunk的updateHash方法。
createHash() { .... }
如:
if(module.hot){}
编译后
if(true){}
打包后
/* 5 */ /***/ (function(module, exports, __webpack_require__) { // webpack-dev-server/client/index.js __webpack_require__(6); //webpack/hot/dev-server __webpack_require__(26); // .src/index.js module.exports = __webpack_require__(28); /***/ })
compilation.plugin("record", function(compilation, records) { if(records.hash === this.hash) return; records.hash = compilation.hash; records.moduleHashs = {}; this.modules.forEach(module => { const identifier = module.identifier(); const hash = require("crypto").createHash("md5"); module.updateHash(hash); records.moduleHashs[identifier] = hash.digest("hex"); }); records.chunkHashs = {}; this.chunks.forEach(chunk => { records.chunkHashs[chunk.id] = chunk.hash; }); records.chunkModuleIds = {}; this.chunks.forEach(chunk => { records.chunkModuleIds[chunk.id] = chunk.mapModules(m => m.id); }); });
compilation.plugin("additional-chunk-assets", function() { .... this.assets[filename] = source; });
module.hot.check(true).then(function(updatedModules) { .... })
本人的简易版webpack实现simple-webpack
(完)
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
在web开发中,webpack的hot module replacement(HMR)功能是可以向运行状态的应用程序定向的注入并更新已经改变的modules。它的出现可以避免像LiveReload那样,任意文件的改变而刷新整个页面。
这个特性可以极大的提升开发拥有运行状态,以及资源文件普遍过多的前端应用型网站的效率。完整介绍可以看官网文档
本文是先从使用者的角度去介绍这个功能,然后从设计者的角度去分析并拆分需要实现的功能和实现的一些细节。
功能介绍
对于使用者来说,体验到这个功能需要以下的配置。
webpack.config.js:
代码: index.js 依赖print.js,使用module.hot.accept接受print.js的更新:
改变print.js代码:
此时服务端向浏览器发送socket信息,浏览器收到消息后,开始下载以hash为名字的下载的json,jsonp文件,如下图:
浏览器会下载对应的hot-update.js,并注入运行时的应用中:
0 代表着所属的chunkid,30代表着所属的moduleid。
替换完之后,执行module.hot.accept的回调函数,如下图:
简单来讲,开启了hmr功能之后,处于accepted状态的module的改动将会以jsonp的形式定向的注入到应用程序中。
一张图来表示HMR的整体流程:
功能分析
提出问题
当翻开bundle.js的时候,你会发现Runtime代码多了许多以下的代码:
打包的时候,明明只引用了4个文件,但是整个打包文件却有30个modules之多:
到现在你可能会有以下几个疑问:
分析问题
功能实现
以上问题,可以从三个不同的角度去解决。server,webpack,brower。
webpack-dev-server
,转换为
构建业务代码时,附带上socketjs,hot代码。
Server.js
浏览器
监听编译器的生命周期模块。
webpack
Template
MainTemplate增加module-obj,module-require事件
module-obj事件负责生成以下代码
module-require事件负责生成以下代码
Compiler
新增Watching类支持watch模式,并结合watchpack监听文件变化。
Module
新增updateHash实现
Chunk
新增updateHash实现
Compilation
增加createHash方法,默认调用md5计算compilation hash。调用依赖树module,chunk的updateHash方法。
Parser
如:
编译后
MultiEntryPlugin
打包后
HotModuleReplacementPlugin
Brower
代码实现
本人的简易版webpack实现simple-webpack
(完)
The text was updated successfully, but these errors were encountered: