我的编程空间,编程开发者的网络收藏夹
学习永远不晚

webpack自动刷新浏览器源码解析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

webpack自动刷新浏览器源码解析

在我们日常的前端开发过程中,在编辑器里只需要保存代码,浏览器就会自动刷新当前页面。这个过程被称为热更新。

其实实现这一功能需要两步:

  • 监听代码的变化
  • 自动刷新浏览器

下面看一下这两个步骤是如何实现的。

配置webpack热更新模式

  • 初识化项目并导入依赖
npm i webpack webpack-cli -D
npm i webpack-dev-server -D
npm i html-webpack-plugin -D

然后,我们需要弄明白,webpack 从版本 webpack@4 之后,需要通过 webpack CLI 来启动服务,提供了启动开发服务的命令。

# 启动开发服务器
webpack serve --mode development --config webpack.config.js
// pkg.json
{
"scripts": {
"dev": "webpack serve --mode development --config webpack.config.js",
"build": "webpack build --mode production --config webpack.config.js"
},
"devDependencies": {
"webpack": "^5.45.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2",
"html-webpack-plugin": "^5.3.2",
}
}

在启动开发服务的时候,在 webpack 的配置文件中配置 ​​devServe​​ 属性,即可开启热更新模式。

// webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
entry: './class="lazy" data-src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
hot: true, // 开启热更新
port: 8080, // 指定服务器端口号
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
})
]
}

源码解析

开启本地服务

首先通过webpack创建了一个compiler实例,然后通过创建自定义server实例,开启了一个本地服务。

// node_modules/webpack-dev-server/bin/webpack-dev-server.js

const webpack = require('webpack');

const config = require('../../webpack.config');

const Server = require('../lib/Server')



const compiler = webpack(config);

const server = new Server(compiler);

server.listen(8080, 'localhost', () => {})

这个自定义Server 不仅是创建了一个http服务,它还基于http服务创建了一个websocket服务,同时监听浏览器的接入,当浏览器成功接入时向它发送hash值,从而实现服务端和浏览器间的双向通信。

// node_modules/webpack-dev-server/lib/Server.js

class Server {

constructor() {

this.setupApp();

this.createServer();

}

//创建http应用

setupApp() {

this.app = express();

}

//创建http服务

createServer() {

this.server = http.createServer(this.app);

}

//监听端口号

listen(port, host, callback) {

this.server.listen(port, host, callback)

this.createSocketServer();

}

//基于http服务创建websocket服务,并注册监听事件connection

createSocketServer() {

const io = socketIO(this.server);

io.on('connection', (socket) => {

this.clientSocketList.push(socket);

socket.emit('hash', this.currentHash);

socket.emit('ok');

socket.on('disconnect', () => {

let index = this.clientSocketList.indexOf(socket);

this.clientSocketList.splice(index, 1)

})

})

}

}



module.exports = Server;

监听编译完成

仅仅在建立websocket连接时,服务端向浏览器发送hash和拉取代码的通知还不够,我们还希望当代码改变时,浏览器也可以接到这样的通知。于是,在开启服务前,还需要对编译完成事件进行监听。

//监听编译完成,当编译完成后通过websocket向浏览器发送广播

setupHooks() {

let { compiler } = this;

compiler.hooks.done.tap('webpack-dev-server', (stats) => {

this.currentHash = stats.hash;

this.clientSocketList.forEach((socket) => {

socket.emit('hash', this.currentHash);

socket.emit('ok');

})

})

}

监听文件修改

要想在代码修改的时候,触发重新编译,那么就需要对代码的变动进行监听。这一步,源码是通过​​webpackDevMiddleware​​​库实现的。库中使用了compiler.watch对文件的修改进行了监听,并且通过​​memory-fs​​实现了将编译的产物存放到内存中,这也是为什么我们在dist目录下看不到变化的内容,放到内存的好处就是为了更快的读写从而提高开发效率。

// node_modules/webpack-dev-middleware/index.js

const MemoryFs = require('memory-fs')

compiler.watch({}, () => {})

let fs = new MemoryFs();

this.fs = compiler.outputFileSystem = fs;

向浏览器中插入客户端代码

前面提到要想实现浏览器和本地服务的通信,那么就需要浏览器接入到本地开启的websocket服务,然而浏览器本身并不具备这样的能力,这就需要我们自己提供这样的客户端代码将它运行在浏览器。因此自定Server在开启http服务之前,就调用了​​updateCompiler()​​方法,它修改了webpack配置中的entry,使得插入的两个文件的代码可以一同被打包到 main.js 中,运行在浏览器。

//node_modules/webpack-dev-server/lib/utils/updateCompiler.js

const path = require('path');

function updateCompiler(compiler) {

compiler.options.entry = {

main: [

path.resolve(__dirname, '../../client/index.js'),

path.resolve(__dirname, '../../../webpack/hot/dev-server.js'),

config.entry,

]

}

}

module.exports = updateCompiler

node_modules /webpack-dev-server/client/index.js

这段代码会放在浏览器作为客户端代码,它用来建立 websocket 连接,当服务端发送hash广播时就保存hash,当服务端发送ok广播时就调用reloadApp()。

let currentHash;

let hotEmitter = new EventEmitter();

const socket = window.io('/');



socket.on('hash', (hash) => {

currentHash = hash;

})

socket.on('ok', () => {

reloadApp();

})



function reloadApp() {

hotEmitter.emit('webpackHotUpdate', currentHash)

}

webpack/hot/dev-server.js

reloadApp()继续调用module.hot.check(),当然第一次加载页面时是不会被调用的。至于这里为啥会分成两个文件,个人理解是为了解藕,每个模块负责不同的分工。

let lastHash;

hotEmitter.on('webpackHotUpdate', (currentHash) => {

if (!lastHash) {

lastHash = currentHash;

return;

}

module.hot.check();

})

module.hot.check()是哪来的?答案是​​HotModuleReplacementPlugin​​。

到此这篇关于webpack自动刷新浏览器源码解析的文章就介绍到这了,更多相关webpack自动刷新浏览器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

webpack自动刷新浏览器源码解析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

webpack自动刷新浏览器源码解析

Webpack自动刷新浏览器是一项非常实用的功能,它可以让开发者在编辑代码时,自动更新浏览器,从而节省大量的时间。那么它是如何实现的呢?
2023-02-07

react如何实现浏览器自动刷新

这篇文章给大家分享的是有关react如何实现浏览器自动刷新的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是前端路由?路由的概念来源于服务端,在服务端中路由描述的是 URL 与处理函数之间的映射关系。在 Web
2023-06-14

vue自定义密码输入框解决浏览器自动填充密码的问题(最新方法)

这篇文章主要介绍了vue自定义密码输入框解决浏览器自动填充密码的问题,通过将密码输入框的type设置为text,修改样式上的显示,来实现既可以让浏览器不自动填充密码,又可以隐藏密码的效果,需要的朋友可以参考下
2023-05-16

vue怎么自定义密码输入框解决浏览器自动填充密码问题

这篇文章主要讲解了“vue怎么自定义密码输入框解决浏览器自动填充密码问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue怎么自定义密码输入框解决浏览器自动填充密码问题”吧!问题描述浏览器
2023-07-06

python自动化测试中装饰器@ddt与@data源码深入解析

最近工作中接触了python自动化测试,所以下面这篇文章主要给大家介绍了关于python自动化测试中装饰器@ddt与@data源码解析的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2022-12-10

编程热搜

目录