(面试)说一下 webpack 的热更新原理?
webpack 通过 watch 可以监测代码的变化;webpack-dev-middleware 可以调用 webpack 暴露的 API 检测代码变化,并且告诉 webpack 将代码保存到内存中;webpack-dev-middleware 通过 sockjs 和 webpack-dev-server/client 建立 webSocket 长连接,将 webpack 打包阶段的各个状态告知浏览器端,最重要的是新模块的 hash 值。webpack-dev-server/client 通过 webpack/hot/dev-server 中的 HMR 去请求新的更新模块,HMR 主要借助 JSONP。先拿到 hash 的 json 文件,然后根据 hash 拼接出更新的文件 js,然后 HotModulePlugin 对比新旧模块和模块依赖完成更新。
搭建 webpack 环境
创建一个项目
mkdir dev-erver && cd dev-server
npm init -y // 快速创建一个项目配置
npm i webpack webpack-dev-server webpack-cli --save-dev
mkdir src // 创建资源目录
mkdir dist // 输出目录
touch webpack.dev.js // 因为是在开发环境需要热更新,所以直接创建dev配置文件
目录结构
webpack 版本
这里说明一下,webpack4 和 webpack5 的配置信息或者显示信息可能有点区别
"devDependencies": {
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"
}
编写配置文件
// webpack.dev.js
"use strict";
const path = require("path");
module.exports = {
entry: "./src/index.js", // 入口文件
output: {
path: path.resolve(__dirname, "dist"), // 输出到哪个文件夹
filename: "output.js", // 输出的文件名
},
mode: "development", // 开发模式
devServer: {
// contentBase: path.resolve(__dirname, 'dist') // contentBase是用来指定被访问html页面所在目录的;
//但是本地报错了,使用下面的语句
static: path.resolve(__dirname, "dist"),
},
};
新建文件
// src/index.js
"use strict";
document.write("hello world~");
package.json 添加一条命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config webpack.dev.js --open"
},
npm run dev 运行
看到文件已经打包完成了,但是在 dist 目录里并没有看到文件,这是因为 WDS 是把编译好的文件放在缓存中,没有放在磁盘上,但是是可以访问到的,
output.js 对应在 webpack 配置文件中的输出文件,配置的是什么就访问什么
http://localhost:8080/output.js
显然想看效果而不是打包后的代码,所以在 dist 目录里创建一个 html 文件引入即可
<script src="./output.js"></script>
感受 webpack 的热更新
内容出来了,接下来修改 index.js 文件,来看下是否可以自动刷新
"use strict";
document.write("hello world~byebye world");
这确实是热更新,但是这种是每一次修改会重新刷新整个页面,可以打开控制台查看。webpack-dev-server 提供了实时重加载的功能,但是不能局部刷新。必须配合后两步的配置才能实现局部刷新,这两步的背后其实是借助了 HotModuleReplacementPlugin。
webpack-dev-server 搭配 HotModuleReplacementPlugin 实现热更新
需要的是,更新修改的模块,但是不要刷新页面。这个时候就需要用到模块热替换。
模块热替换(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新各种模块,而无需进行完全刷新。
特性
模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:
保留在完全重新加载页面时丢失的应用程序状态。
只更新变更内容,以节省宝贵的开发时间。
调整样式更加快速 - 几乎相当于在浏览器调试器中更改样式。
启用
// webpack.dev.js
const path = require("path");
const webpack = require("webpack"); // 主要多了这一行
module.exports = {
entry: "./src/index.js", // 入口文件
output: {
path: path.resolve(__dirname, "dist"), // 输出到哪个文件夹
filename: "output.js", // 输出的文件名
},
mode: "development", // 开发模式
devServer: {
// contentBase: path.resolve(__dirname, 'dist') // contentBase是用来指定被访问html页面所在目录的;但是本地报错了,使用下面的语句
static: path.resolve(__dirname, "dist"),
hot: true, // 主要多了这一行
},
plugins: [
// 主要多了这一行
new webpack.HotModuleReplacementPlugin(),
],
};
修改一下文件,形成引用关系
//index.js
import { test } from "./page1.js";
document.write("hello world~1234");
test();
//page1.js
module.exports = {
test: function () {
console.log(11111);
},
};
在入口页 index.js 面再添加一段
if (module.hot) {
module.hot.accept();
}
思考
标签:浏览器,dev,server,webpack,更新,模块,原理,js From: https://www.cnblogs.com/wp-leonard/p/17839305.html