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 相关文章推荐
在视频前插入广告
Nov 20 Javascript
在JavaScript中遭遇级联表达式陷阱
Mar 08 Javascript
wap浏览自动跳转到wap页面的js代码
May 17 Javascript
jquery拖拽排序简单实现方法(效果增强版)
Feb 16 Javascript
jQuery防止重复绑定事件的解决方法
May 14 Javascript
微信禁止下拉查看URL的处理方法
Sep 28 Javascript
微信、QQ、微博、Safari中使用js唤起App
Jan 24 Javascript
Vue项目自动转换 px 为 rem的实现方法
Oct 29 Javascript
微信小程序导航栏滑动定位功能示例(实现CSS3的positionsticky效果)
Jan 24 Javascript
vue router总结 $router和$route及router与 router与route区别
Jul 05 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
Oct 30 Javascript
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 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输出控制功能在简繁体转换中的应用
2006/10/09 PHP
IIS php环境配置PHP5 MySQL5 ZendOptimizer phpmyadmin安装与配置
2008/11/18 PHP
用js实现的一个Flash滚动轮换显示图片代码生成器
2007/03/14 Javascript
基于JQuery实现的图片自动进行缩放和裁剪处理
2014/01/31 Javascript
javascript页面加载完执行事件代码
2014/02/11 Javascript
jQuery实现仿新浪微博浮动的消息提示框(可智能定位)
2015/10/10 Javascript
BootStrap网页中代码显示用法详解
2016/10/21 Javascript
Angular.js中处理页面闪烁的方法详解
2017/03/09 Javascript
使用bootstrap-paginator.js 分页来进行ajax 异步分页请求示例
2017/03/09 Javascript
javascript 的变量、作用域和内存问题
2017/04/19 Javascript
Javarscript中模块(module)、加载(load)与捆绑(bundle)详解
2017/05/28 Javascript
angular实现页面打印局部功能的思考与方法
2018/04/13 Javascript
微信小程序实现无限滚动列表
2020/05/29 Javascript
Jquery滑动门/tab切换实现方法完整示例
2020/06/05 jQuery
python命令行参数用法实例分析
2019/06/25 Python
python 图片去噪的方法示例
2019/07/09 Python
Python Selenium参数配置方法解析
2020/01/19 Python
Jupyter notebook如何修改平台字体
2020/05/13 Python
Python延迟绑定问题原理及解决方案
2020/08/04 Python
Python基于gevent实现文件字符串查找器
2020/08/11 Python
Python中return函数返回值实例用法
2020/11/19 Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
2021/02/25 Python
经济实惠的豪华家具:My-Furniture
2019/03/12 全球购物
都柏林通行卡/城市通票:The Dublin Pass
2020/02/16 全球购物
网上书店创业计划书
2014/01/12 职场文书
文明寄语大全
2014/04/11 职场文书
舞蹈兴趣小组活动总结
2014/07/07 职场文书
民主生活会对照检查材料
2014/09/22 职场文书
党员学习新党章思想汇报
2014/10/25 职场文书
农村党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
2014年乡镇纪委工作总结
2014/12/19 职场文书
2015年国庆节标语大全
2015/07/30 职场文书
Nginx配置https原理及实现过程详解
2021/03/31 Servers
英国数字版游戏销量周榜公布 《小缇娜的奇幻之地》登顶
2022/04/03 其他游戏
解决Git推送错误non-fast-forward的方法
2022/06/25 Servers
利用Python实时获取steam特惠游戏数据
2022/06/25 Python