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汉字转拼音实现代码
Feb 06 Javascript
jQuery获取注册信息并提示实现代码
Apr 21 Javascript
JQuery设置和去除disabled属性的5种方法总结
May 16 Javascript
JS中的prototype与面向对象的实例讲解
May 22 Javascript
jQuery获得指定元素坐标的方法
Apr 14 Javascript
jQuery动态添加
Apr 07 Javascript
javascript中去除数组重复元素的实现方法【实例】
Apr 12 Javascript
微信小程序 在Chrome浏览器上运行以及WebStorm的使用
Sep 27 Javascript
详解使用vue-router进行页面切换时滚动条位置与滚动监听事件
Mar 08 Javascript
基于jquery实现多级菜单效果
Jul 25 jQuery
nuxt.js写项目时增加错误提示页面操作
Nov 05 Javascript
在vue项目中封装echarts的步骤
Dec 25 Vue.js
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调用mysql数据 dbclass类
2011/05/07 PHP
php学习之流程控制实现代码
2011/06/09 PHP
PHP人民币金额数字转中文大写的函数代码
2013/02/27 PHP
php小技巧之过滤ascii控制字符
2014/05/14 PHP
在Windows系统下使用PHP生成Word文档的教程
2015/07/03 PHP
使用jquery实现图文切换效果另加特效
2013/01/20 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
2014/05/05 Javascript
javascript控制在光标位置插入文字适合表情的插入
2014/06/09 Javascript
详解vue表单验证组件 v-verify-plugin
2017/04/19 Javascript
js实现轮播图的两种方式(构造函数、面向对象)
2017/09/30 Javascript
写给小白看的JavaScript异步
2017/11/29 Javascript
vue中进入详情页记住滚动位置的方法(keep-alive)
2018/09/21 Javascript
如何在Vue中使用CleaveJS格式化你的输入内容
2018/12/14 Javascript
JS判断两个数组或对象是否相同的方法示例
2019/02/28 Javascript
layui关闭层级、简单监听的实例
2019/09/06 Javascript
深入理解 TypeScript Reflect Metadata
2019/12/12 Javascript
Node.js Domain 模块实例详解
2020/03/18 Javascript
深度解读vue-resize的具体用法
2020/07/08 Javascript
JavaScript如何实现监听键盘输入和鼠标监点击
2020/07/20 Javascript
布同自制Python函数帮助查询小工具
2011/03/13 Python
python中列表元素连接方法join用法实例
2015/04/07 Python
python3+PyQt5实现支持多线程的页面索引器应用程序
2018/04/20 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
纯CSS3实现扇形动画菜单(简化版)实例源码
2017/01/17 HTML / CSS
解决margin 外边距合并问题
2019/07/03 HTML / CSS
HTML5的表单(绝对特别强大的功能)使用示例
2013/06/20 HTML / CSS
详解通过HTML5 Canvas实现图片的平移及旋转变化的方法
2016/03/22 HTML / CSS
采购经理岗位职责
2014/02/16 职场文书
高中军训感想300字
2014/03/04 职场文书
QQ空间主人寄语大全
2014/04/12 职场文书
课外活动总结范文
2014/07/09 职场文书
2016党员干部政治学习心得体会
2016/01/23 职场文书
小学教代会开幕词
2016/03/04 职场文书
Python3中最常用的5种线程锁实例总结
2021/07/07 Python
《战锤40K:暗潮》跳票至9月 公布新宣传片
2022/04/03 其他游戏
springboot应用服务启动事件的监听实现
2022/04/06 Java/Android