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 相关文章推荐
利用JQuery动画制作滑动菜单项效果实现步骤及代码
Feb 07 Javascript
用js模拟struts2的多action调用示例
May 19 Javascript
js实现照片墙功能实例
Feb 05 Javascript
JavaScript比较两个对象是否相等的方法
Feb 06 Javascript
JS+CSS实现的竖向简洁折叠菜单效果代码
Oct 22 Javascript
JavaScript提升性能的常用技巧总结【经典】
Jun 20 Javascript
bootstrap基础知识学习笔记
Nov 02 Javascript
Angular4学习笔记router的简单使用
Mar 30 Javascript
jquery操作select常见方法大全【7种情况】
May 28 jQuery
JS监听组合按键思路及实现过程
Apr 17 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
Aug 17 Javascript
基于原生JS封装的Modal对话框插件的示例代码
Sep 09 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中usort在值相同时改变原始位置问题的解决方法
2011/11/27 PHP
解析php session_set_save_handler 函数的用法(mysql)
2013/06/29 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
PHP4和PHP5版本下解析XML文档的操作方法实例分析
2017/05/20 PHP
用JavaScript将从数据库中读取出来的日期型格式化为想要的类型。
2009/08/15 Javascript
suggestion开发小结以及对键盘事件的总结(针对中文输入法状态)
2011/12/20 Javascript
js隐式全局变量造成的bug示例代码
2014/04/22 Javascript
Jquery api 速查表分享
2015/01/12 Javascript
JavaScript简单实现鼠标移动切换图片的方法
2016/02/23 Javascript
JavaScript 中有关数组对象的方法(详解)
2016/08/15 Javascript
基于KO+BootStrap+MVC实现的分页控件代码分享
2016/11/07 Javascript
Node.js中.pfx后缀文件的处理方法
2017/03/10 Javascript
Vue 项目分环境打包的方法示例
2018/08/03 Javascript
vue动态设置img的src路径实例
2018/09/18 Javascript
详解angular2如何手动点击特定元素上的点击事件
2018/10/16 Javascript
原生JS实现随机点名项目的实例代码
2019/04/30 Javascript
ES6中定义类和对象的方法示例
2019/07/31 Javascript
JavaScript将数组转换为链表的方法
2020/02/16 Javascript
js闭包和垃圾回收机制示例详解
2021/03/01 Javascript
Python yield使用方法示例
2013/12/04 Python
Python使用ftplib实现简易FTP客户端的方法
2015/06/03 Python
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
2017/07/24 Python
python 文件查找及内容匹配方法
2018/10/25 Python
基于Django ORM、一对一、一对多、多对多的全面讲解
2019/07/26 Python
调整Jupyter notebook的启动目录操作
2020/04/10 Python
Python读取yaml文件的详细教程
2020/07/21 Python
Python 如何查找特定类型文件
2020/08/17 Python
PyTorch中clone()、detach()及相关扩展详解
2020/12/09 Python
大学四年职业生涯规划书范文
2014/01/02 职场文书
杠杆的科学教学反思
2014/01/10 职场文书
中级会计职业生涯规划书
2014/03/01 职场文书
群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
学校证明范文
2015/06/24 职场文书
校运会通讯稿
2015/07/18 职场文书
日本十大血腥动漫,那些被禁播的动漫盘点
2022/03/21 日漫
SpringBoot2零基础到精通之数据与页面响应
2022/03/22 Java/Android