webpack 模块热替换原理


Posted in Javascript onApril 09, 2018

全称是Hot Module ReplaceMent(HMR),理解成热模块替换或者模块热替换都可以吧,和.net中的热插拔一个意思,就是在运行中对程序的模块进行更新。这个功能主要是用于开发过程中,对生产环境没有任何帮助(这一点区别.net热插拔)。效果上就是界面的无刷新更新。

HMR基于WDS,style-loader可以通过它来实现无刷新更新样式。但是对于JavaScript模块就需要做一点额外的处理,怎么处理继续往下看。因为HMR是用于开发环境的,所以我们修改下配置,做两份准备。一个用于生产,一个用于开发。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

const PATHS = {
 app: path.join(__dirname, 'app'),
 build: path.join(__dirname, 'build'),
};

const commonConfig={
 entry: {
  app: PATHS.app,
 },
 output: {
  path: PATHS.build,
  filename: '[name].js',
 },
 plugins: [
  new HtmlWebpackPlugin({
   title: 'Webpack demo',
  }),
 ],
}
 
function developmentConfig(){
 const config ={
  devServer:{
   //使能历史记录api
   historyApiFallback:true,
    hotOnly:true,//关闭热替换 注释掉这行就行
    stats:'errors-only',
   host:process.env.Host,
   port:process.env.PORT,
   overlay:{
    errors:true,
    warnings:true,
   }
  },
   plugins: [
   new webpack.HotModuleReplacementPlugin(),
  ],
 };
  return Object.assign(
  {},
  commonConfig,
  config,
  {
   plugins: commonConfig.plugins.concat(config.plugins),
  }
 );
}

module.exports = function(env){
 console.log("env",env);
 if(env=='development'){
  return developmentConfig();
 }
  return commonConfig;
};

这个webpack.config.js建立了两个配置,一个是commonConfig,一个是developmentConfig 两者通过env参数来区分,但这个env参数是怎么来的呢?我们看看之前的package.json中的一段:

webpack 模块热替换原理

也就是说,如果按照上面的这个配置,我们通过npm start 启动的话,进入的就是开发环境配置,如果是直接build,那么就是生产环境的方式。build方式是第一节里面讲的 直接通过npm启动webpack,这就不带WDS了。另外有了一个Object.assign语法,将配置合并。这个时候通过npm start启动,控制台打印出了两条日志。

webpack 模块热替换原理

看起来HRM已经启动了。但是此时更新一下component.js

webpack 模块热替换原理

日志显示没有东西被热更新。而且这个39,36代表的是模块Id,看起来很不直观,这里可以通过一个插件使其更符合人意

plugins: [
   new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
  ],

这个时候再启动。

webpack 模块热替换原理

这样名称就直观了。但是我们期待的更新还是没有出来。因为需要实现一个接口

import component from './component';
let demoComponent=component();
document.body.appendChild(demoComponent);

//HMR 接口
if(module.hot){
  module.hot.accept('./component',()=>{
    const nextComponent=component();
    document.body.replaceChild(nextComponent,demoComponent);
    demoComponent=nextComponent;
  })
}

并修改component.js:

export default function () {
 var element = document.createElement('h1');
 element.innerHTML = 'Hello webpack';
 return element;
}

webpack 模块热替换原理

这个时候页面更新了。每次改动页面上都会增加一个带有hot-update.js ,类似于下面这样:

webpackHotUpdate(0,{

/***/ "./app/component.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony default export */ __webpack_exports__["default"] = function () {
 var element = document.createElement('h1');
 element.innerHTML = 'Hello web ';
 element.className='box';
 return element;
};

/***/ })

})

通过webpackHotUpdate对相应模块进行更新。0表示模块的id,"./app/component.js"表示模块对应的name。结构是webpack(id,{key:function(){}})。function外带了一个括号,不知道有什么作用。webpackHotUpdate的定义是这样的:

this["webpackHotUpdate"] = 
 function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars  
     hotAddUpdateChunk(chunkId, moreModules);
    if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);
  } ;

小结:从结构来看,一个是id,一个是对应修改的模块。但实际执行更新的是hotApply方法。热更新整个机制还是有点复杂,效果上像MVVM的那种绑定。有兴趣的可以深入研究下。不建议在生产使用HMR,会让整体文件变大,而且对生成没有什么帮助,在下一节会讲样式的加载,style-loader就是用到了HMR。但对于js模块还要写额外的代码,这让人有点不爽。

demo:webpack-ch3_3water.rar

参考:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS基础之undefined与null的区别分析
Aug 08 Javascript
jquery()函数的三种语法介绍
Oct 09 Javascript
iframe子页面获取父页面元素的方法
Nov 05 Javascript
Javascript与jQuery方法的隐藏与显示
Jan 19 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
Jul 17 Javascript
jQuery实现点击水纹波动动画
Apr 10 Javascript
JavaScript事件学习小结(五)js中事件类型之鼠标事件
Jun 09 Javascript
Bootstrap笔记之缩略图、警告框实例详解
Mar 09 Javascript
node(koa2) web应用模块介绍详解
Mar 29 Javascript
回顾Javascript React基础
Jun 15 Javascript
jQuery提示框插件SweetAlert用法分析
Aug 05 jQuery
Vue 中 filter 与 computed 的区别与用法解析
Nov 21 Javascript
Angular5升级RxJS到5.5.3报错:EmptyError: no elements in sequence的解决方法
Apr 09 #Javascript
浅谈webpack 自动刷新与解析
Apr 09 #Javascript
webpack 插件html-webpack-plugin的具体使用
Apr 09 #Javascript
详解webpack 入门与解析
Apr 09 #Javascript
vue技术分享之你可能不知道的7个秘密
Apr 09 #Javascript
一步步教会你微信小程序的登录鉴权
Apr 09 #Javascript
vue组件详解之使用slot分发内容
Apr 09 #Javascript
You might like
php文档更新介绍
2011/07/22 PHP
php正则表达式使用的详细介绍
2013/04/27 PHP
php实现微信企业号支付个人的方法详解
2017/07/26 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
2019/05/06 PHP
基于JQuery实现的图片自动进行缩放和裁剪处理
2014/01/31 Javascript
jQuery基于当前元素进行下一步的遍历
2014/05/20 Javascript
jQuery获取节点和子节点文本的方法
2014/07/22 Javascript
javaScript的函数对象的声明详解
2015/02/06 Javascript
JavaScript实现16进制颜色值转RGB的方法
2015/02/09 Javascript
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
2016/08/29 Javascript
浅谈jQuery中的eq()与DOM中element.[]的区别
2016/10/28 Javascript
Bootstrap显示与隐藏简单实现代码
2017/03/06 Javascript
AngularJS实现动态添加Option的方法
2017/05/17 Javascript
JS按条件 serialize() 对应标签的使用方法
2017/07/24 Javascript
JS求1到任意数之间的所有质数的方法详解
2019/05/20 Javascript
使用Angular9和TypeScript开发RPG游戏的方法
2020/03/25 Javascript
js实现mp3录音通过websocket实时传送+简易波形图效果
2020/06/12 Javascript
[04:42]5分钟带你了解什么是DOTA2(第一期)
2017/02/07 DOTA
python字符串连接的N种方式总结
2014/09/17 Python
Python中if __name__ == '__main__'作用解析
2015/06/29 Python
python数据处理实战(必看篇)
2017/06/11 Python
python登录WeChat 实现自动回复实例详解
2019/05/28 Python
Python字符串的一些操作方法总结
2019/06/10 Python
Python Pandas 转换unix时间戳方式
2019/12/07 Python
在pytorch 中计算精度、回归率、F1 score等指标的实例
2020/01/18 Python
matlab中imadjust函数的作用及应用举例
2020/02/27 Python
Python实现发票自动校核微信机器人的方法
2020/05/22 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
2020/05/26 Python
上海某公司.net方向笔试题
2014/09/14 面试题
Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
2015/01/27 面试题
介绍一些UNIX常用简单命令
2014/11/11 面试题
员工考核管理制度
2014/02/02 职场文书
婚前财产协议书范本
2014/10/19 职场文书
小学大队委竞选口号
2015/12/25 职场文书
党风廉政建设心得体会(2016最新版)
2016/01/22 职场文书
2016年学校“3.12”植树节活动总结
2016/03/16 职场文书