当前位置:首页 > 谈天说地 > 正文内容

webpack热更新是什么(webpack热更新原理)

34资源网2022年02月23日 15:04392
背景

传统开发页面,每次更新的时候需要我们手动刷新浏览器才会更新。自从构建工具横空出世。我们可以通过热更新的方式来进行更新。通称HMR(hot module replacement),也就是模块热替换,当你每次需要更新代码的时候,不在需要手动刷新即可实现效果预览。

前置知识

探究热更新是怎么实现之前,我们需要知道几样东西

  • sockjs
  • webpack.HotModuleReplacementPlugin
  • memory-fs
  • webpack-dev-middleware
  • webpack一些知识和一些底层知识,否则你估计会看不懂,并且属于懵逼状态,对于一些东西都给出了链接
  • Compiler事件流
memory-fs

内存文件系统,webpack默认生成的文件会丢到内存中,并不会直接写入硬盘

webpack.HotModuleReplacementPlugin

中文文档

英文文档

这个是HMR实现核心,由webpack内部所提供的一个插件,该插件会提供一些方法,用于检查变更,并告诉你每次变更所生成的文件hash

sockjs

用于发送socket请求,通知浏览器进行更改

webpack-dev-middleware

webpack-dev-middleware会接收一个webpack所返回的一个compiler对象,然后调用compiler.watch监听文件更改,

我们知道webpack热更新的时候,并不会写入硬盘中,这是因为默认的情况下是写入内存的,因为内存的读取速度比硬盘会快很多,我们可以通过devServer.writeToDisk来修改

if (options.writeToDisk) {
    // 写入硬盘
} else {
    // 写入内存,并设置内存中的路径为当前路径
    const memoryFs = new MemoryFs()
}
复制代码

这样我们就可以知道文件是否更改,并且把文件存在了内存中,现在在回到webpack-dev-server

HMR是怎么实现的

这里用webpack-dev-server进行举例,所有热更新原理基本类似。手写我们实现一个简单的webpack配置文件。

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

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js'
    },
    devServer: {
        host: 'localhost',
        contentBase: path.resolve(__dirname, 'src')
        port: 8080,
        hot: true,
        open: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HtmlWebpackPlugin({
            template: './src/pages/index.html',
            filename: 'index.html'
        })
    ]
}
复制代码
简单实现

这是一个简单的流程图,不涉及任何复杂逻辑,这图中我们需要关注几个问题

  1. 为什么需要启动
  2. 为什么需要添加webpack.HotModuleReplacementPlugin
  3. webpack-dev-server怎么知道文件发生了变化
  4. 如何实现更新

现在我们有了上面的问题,来逐个去看下

  1. 为什么需要webpack.HotModuleReplacementPlugin

这个是webpack官方所提供的插件,该插件提供了一些方法,当我们启动的时候webpack会给每个文件注入moudle一个对象,这个对象里面有个module.hot对象,具体可以参考 中文文档 ,并且webpack每次重新构建的时候会生成一个hash,当我们把devServer.writeToDisk设置为true的时候,每次更改还会生成这2个文件。

  • hot-update.js是每次需要更新的文件
  • hot-update.json下次更新需要生成的hash
[id].[fullhash].hot-update.js
[runtime].[fullhash].hot-update.json
复制代码
  1. webpack-dev-server怎么知道文件发生了变化

这个问题比较简单,webpack-dev-server启动的时候,初始化了express,并且把expres传递给了webpack-dev-middleware,webpack-dev-middleware也是webpack团队出品,devServer几乎所有api都是通过这个库去实现的。

webpack构建的时候会返回一个compiler对象,该对象会提供一个watch方法用来监听文件更改,而webpack-dev-middleware就是通过这种方法监听文件更改,
webpack.HotModuleReplacementPlugin也是一样的操作。并且每次重新构建的时候webpack-dev-server都会监听compiler的compile、invalid、done方法,会通知socket服务用于是否展示overlay(遮罩层)。

  • compile 在compilation生成之前,compilation是webpack每次重新编译所返回的一个对象
  • invalid 编译失败
  • done 编译成功
  1. 如何实现更新

webpack-dev-server在启动的时候还会给entry添加2个文件

webpack-dev-server/clinet/index.js
webpack/hot/devServer.js // 如果设置了hotonly会注入webpack/hot/only-dev-server
复制代码

现在我们知道了每次构建所产生的hash,和产生的文件,但这时候还没办法热更新。我们可以记录每次构建所生成的hash,用于判断和当前的hash是否匹配,从而实现热更新,并且通知浏览器进行更新。


webpack-dev-server/client/index.js负责每次更新的状态,当状态为ok和warinings的时候会执行一个reloadApp方法,该方法会emit一个webpackHotUpdate事件,并把变更的文件hash传递出去,然后webpack/hot/devServer.js负责监听这个事件,当监听到该事件的时候,保存该文件hash,并且判断hash是否已更新并且module.hot.status为idle的时候,执行一个check方法,check会拿到一个需要更新的模块,如果有需要更新,则调用location.reload()方法,进行更新。

if (module.hot) {
	var lastHash;
	var upToDate = function upToDate() {
		return lastHash.indexOf(__webpack_hash__) >= 0;
	};
	var log = require("./log");
	var check = function check() {
		module.hot
			.check(true)
			.then(function(updatedModules) {
				if (!updatedModules) {
					log("warning", "[HMR] Cannot find update. Need to do a full reload!");
					log(
						"warning",
						"[HMR] (Probably because of restarting the webpack-dev-server)"
					);
					window.location.reload();
					return;
				}

				if (!upToDate()) {
					check();
				}

				require("./log-apply-result")(updatedModules, updatedModules);

				if (upToDate()) {
					log("info", "[HMR] App is up to date.");
				}
			})
			.catch(function(err) {
				var status = module.hot.status();
				if (["abort", "fail"].indexOf(status) >= 0) {
					log(
						"warning",
						"[HMR] Cannot apply update. Need to do a full reload!"
					);
					log("warning", "[HMR] " + log.formatError(err));
					window.location.reload();
				} else {
					log("warning", "[HMR] Update failed: " + log.formatError(err));
				}
			});
	};
	var hotEmitter = require("./emitter");
	hotEmitter.on("webpackHotUpdate", function(currentHash) {
		lastHash = currentHash;
		if (!upToDate() && module.hot.status() === "idle") {
			log("info", "[HMR] Checking for updates on the server...");
			check();
		}
	});
	log("info", "[HMR] Waiting for update signal from WDS...");
} else {
	throw new Error("[HMR] Hot Module Replacement is disabled.");
}
复制代码

现在我们已经大概了解了热更新的过程。

看完文章,还可以用支付宝扫描下面的二维码领取一个支付宝红包,目前可领1-88元不等

支付宝红包二维码

除了扫码可以领取之外,大家还可以(复制 720087999 打开✔支付宝✔去搜索, h`o`n.g.包哪里来,动动手指就能领)。

看下图所示是好多参与这次活动领取红包的朋友:

支付宝红包

扫描二维码推送至手机访问。

版权声明:本文由34楼发布,如需转载请注明出处。

本文链接:https://www.34l.com/post/8469.html

分享给朋友:

相关文章

英国正在调查一种新出现的变异病毒
英国正在调查一种新出现的变异病毒

新华社伦敦3月11日电(记者张家伟 金晶)英国英格兰公共卫生局11日表示,该国近期确诊两例感染了一种新的变异新冠病毒的病例,目前正在对这一新的变异病毒开展调查。英格兰公共卫生局说,这两例病例是近期在英格兰东南部被确诊的,该局已于3月4日将该...

初中生创业可以做什么?适合初中生干的创业项目推荐
初中生创业可以做什么?适合初中生干的创业项目推荐

现如今很多初中生因为家里经济条件不是很好,不得已早早的就辍学创业了。那么,初中生创业可以做什么好呢?很多初中生对于刚开始创业很迷糊,不知道该做什么好,接下来小编就给大家推荐几种适合初中生干的创业项目,想创业挣钱的初中生朋友好好看下吧。1、手...

养成良好的习惯,做一名有品位的教师
养成良好的习惯,做一名有品位的教师

陶行知先生说:“思想决定行动,行动养成习惯,习惯形成品质,品质决定命运”。最近从网上读了《影响教师一生的100个好习惯》一书,不禁对陶先生这句话有了更深刻的领悟和理解。阅读本书带给我的不仅是享受,更多的则是生活的引领,智慧的传递和方法的教授...

最傻的六种员工离职理由,希望你不是其中一员
最傻的六种员工离职理由,希望你不是其中一员

春节后,今年的中国员工离职率应该是最低的。但是职场上,还是会有很多员工提离职。离职原因各种各样, 不开心,不舒服,工资少,学不到东西等等。那么,最傻的六种员工离职是哪些呢?一、新领导到来有些员工习惯了以前的领导的工作方式,怕自己不适应新领导...

谈2022年平衡发展策略,我们要平衡的发展
谈2022年平衡发展策略,我们要平衡的发展

2022年解决方案的第二个关键词叫平衡。我们要平衡的发展,长期的发展。你的个人生活,你的公司事业,还有国家的形势,我觉得一定要平衡的去发展,不能说我只赚钱,身体就搞垮,或者说我只赚快钱,但是不关心国家的形势。你看,密室逃脱这个行业,上周国家...

引流文案微信推广(微商引流推广文案模板)
引流文案微信推广(微商引流推广文案模板)

大家好啊!今天又跟大家分享小技巧啦~往下看↓↓↓ 首先说一下什么样的文案是引流型的?实际上,一句话是将公共域流量定向到您的私有域流量池。其目的是先引流然后慢慢进行信任激活变现。 在标题方面,通常有以下几种类型,今天为大家详细描述一下。...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。