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 相关文章推荐
JavaScript null和undefined区别分析
Oct 14 Javascript
Jquery css函数用法(判断标签是否拥有某属性)
May 28 Javascript
基于jquery实现的类似百度搜索的输入框自动完成功能
Aug 23 Javascript
JS 获取滚动条高度示例代码
Oct 24 Javascript
Javascript中封装window.open解决不兼容问题
Sep 28 Javascript
原生js实现类似弹窗抖动效果
Apr 02 Javascript
用NODE.JS中的流编写工具是要注意的事项
Mar 01 Javascript
jQuery+vue.js实现的九宫格拼图游戏完整实例【附源码下载】
Sep 12 jQuery
原生javascript AJAX 三级联动的实现代码
May 04 Javascript
Node.js使用supervisor进行开发中调试的方法
Mar 26 Javascript
webpack 代码分离优化快速指北
May 18 Javascript
Vue实现可移动水平时间轴
Jun 29 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/06/13 PHP
基于PHP静态类的原罪详解
2013/05/06 PHP
使用Curl进行抓取远程内容时url中文编码问题示例探讨
2013/10/29 PHP
php实现可用于mysql,mssql,pg数据库操作类
2014/12/13 PHP
PHP使用Redis替代文件存储Session的方法
2017/02/15 PHP
php基于协程实现异步的方法分析
2019/07/17 PHP
PHP设计模式(六)桥连模式Bridge实例详解【结构型】
2020/05/02 PHP
php array_map()函数实例用法
2021/03/03 PHP
数理公式,也可以这么唯美
2021/03/10 无线电
限制上传文件大小和格式的jQuery插件实例
2015/01/24 Javascript
浅谈JQuery+ajax+jsonp 跨域访问
2016/06/25 Javascript
Vue.js中数组变动的检测详解
2016/10/12 Javascript
JS解决position:sticky的兼容性问题的方法
2017/10/17 Javascript
three.js实现3D模型展示的示例代码
2017/12/31 Javascript
React通过redux-persist持久化数据存储的方法示例
2019/02/14 Javascript
Vue.js下拉菜单组件使用方法详解
2019/10/19 Javascript
浅谈vuex为什么不建议在action中修改state
2020/02/02 Javascript
Python中property属性实例解析
2018/02/10 Python
Python反转序列的方法实例分析
2018/03/21 Python
Python3导入CSV文件的实例(跟Python2有些许的不同)
2018/06/22 Python
python实现截取屏幕保存文件,删除N天前截图的例子
2019/08/27 Python
使用matplotlib绘制图例标签中带有公式的图
2019/12/13 Python
Python实现实时数据采集新型冠状病毒数据实例
2020/02/04 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
Python常用GUI框架原理解析汇总
2020/12/07 Python
CSS3解决移动页面上点击链接触发色块的问题
2016/06/03 HTML / CSS
澳大利亚制造的蜡烛和扩散器:Glasshouse Fragrances
2018/05/20 全球购物
个人教师自我评价范文
2013/12/02 职场文书
《夸父追日》教学反思
2014/02/26 职场文书
大学生求职信例文
2014/06/29 职场文书
感情真挚的毕业生求职信
2014/07/19 职场文书
临时租车协议范本
2014/09/23 职场文书
政府四风问题整改措施
2014/10/04 职场文书
郭明义观后感
2015/06/08 职场文书
四风之害观后感
2015/06/09 职场文书
600字作文之感受大自然
2019/11/27 职场文书