使用JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)易的熱更新
什么是熱更新
熱更新是指在應(yīng)用程序運(yùn)行時(shí),對(duì)程序的部分內(nèi)容進(jìn)行更新,而無(wú)需重啟整個(gè)應(yīng)用程序。通常,熱更新是在不停止整個(gè)應(yīng)用程序的情況下,將新的代碼、資源或配置應(yīng)用于正在運(yùn)行的應(yīng)用程序,以實(shí)現(xiàn)功能修復(fù)、性能優(yōu)化或新增功能等目的。
熱更新的優(yōu)點(diǎn)
實(shí)時(shí)反饋,提高開(kāi)發(fā)效率:熱更新允許開(kāi)發(fā)人員在進(jìn)行代碼更改后立即看到結(jié)果,無(wú)需重新編譯和重啟應(yīng)用程序。這大大減少了開(kāi)發(fā)、測(cè)試和調(diào)試代碼所需的時(shí)間,提高了開(kāi)發(fā)效率。
保持應(yīng)用程序狀態(tài):通過(guò)熱更新,應(yīng)用程序的狀態(tài)可以在代碼更改時(shí)得以保留。這意味著開(kāi)發(fā)人員不需要在每次更改后重新導(dǎo)航到特定頁(yè)面或重現(xiàn)特定的應(yīng)用程序狀態(tài),從而節(jié)省了時(shí)間和精力。
webpack 中的熱更新
在Webpack中,熱更新(Hot Module Replacement,HMR)是一種通過(guò)在應(yīng)用程序運(yùn)行時(shí)替換代碼的技術(shù),而無(wú)需重新加載整個(gè)頁(yè)面或應(yīng)用程序。它提供了一種高效的開(kāi)發(fā)方式,可以在開(kāi)發(fā)過(guò)程中快速看到代碼更改的效果,而不中斷應(yīng)用程序的狀態(tài)。
原理如下:
客戶端連接到開(kāi)發(fā)服務(wù)器:當(dāng)啟動(dòng)Webpack開(kāi)發(fā)服務(wù)器時(shí),它會(huì)在瀏覽器中創(chuàng)建一個(gè)WebSocket連接。
打包和構(gòu)建模塊:在開(kāi)發(fā)模式下,Webpack會(huì)監(jiān)視源代碼文件的變化,并在代碼更改時(shí)重新打包和構(gòu)建模塊。這些模塊構(gòu)成了應(yīng)用程序的各個(gè)部分。
將更新的模塊發(fā)送到瀏覽器:一旦Webpack重新構(gòu)建了模塊,它會(huì)將更新的模塊代碼通過(guò)WebSocket發(fā)送到瀏覽器端。
瀏覽器接收并處理更新的模塊:瀏覽器接收到來(lái)自Webpack的更新模塊代碼后,會(huì)根據(jù)模塊的標(biāo)識(shí)進(jìn)行處理。它使用模塊熱替換運(yùn)行時(shí)(Hot Module Replacement Runtime)來(lái)執(zhí)行以下操作:(個(gè)人理解就像是 AJAX 局部刷新的過(guò)程,不對(duì)請(qǐng)指出)
(1)找到被替換的模塊并卸載它。
(2)下載新的模塊代碼,并對(duì)其進(jìn)行注入和執(zhí)行。
(3)重新渲染或更新應(yīng)用程序的相關(guān)部分。
保持應(yīng)用程序狀態(tài):熱更新通過(guò)在模塊替換時(shí)保持應(yīng)用程序狀態(tài)來(lái)確保用戶不會(huì)失去當(dāng)前的狀態(tài)。這意味著在代碼更改后,開(kāi)發(fā)人員可以繼續(xù)與應(yīng)用程序進(jìn)行交互,而無(wú)需手動(dòng)重新導(dǎo)航到特定頁(yè)面或重現(xiàn)特定狀態(tài)。
代碼模擬
在同一個(gè)目錄下創(chuàng)建 server.js 和 watcher.js
server.js
const http = require("http");
const server = http.createServer((req, res) => {
res.statusCode = 200;
// 設(shè)置字符編碼為 UTF-8,若有中文也不亂碼
res.setHeader("Content-Type", "text/plain; charset=utf-8");
res.end("offer get!!!");
});
server.listen(7777, () => {
console.log("服務(wù)已啟動(dòng)在 7777 端口");
process.send("started");
});
// 監(jiān)聽(tīng)來(lái)自 watcher.js 的消息
process.on("message", (message) => {
if (message === "refresh") {
// 重新加載資源或執(zhí)行其他刷新操作
console.log("重新加載資源");
}
});(1)使用 http.createServer 方法創(chuàng)建一個(gè) HTTP 服務(wù)器實(shí)例,該服務(wù)器將監(jiān)聽(tīng)來(lái)自客戶端的請(qǐng)求。
(2)啟動(dòng)服務(wù),當(dāng)服務(wù)器成功啟動(dòng)并開(kāi)始監(jiān)聽(tīng)指定端口時(shí),回調(diào)函數(shù)將被調(diào)用。
(3)通過(guò)調(diào)用 process.send 方法,我們向父進(jìn)程發(fā)送一條消息,消息內(nèi)容為字符串 "started",表示服務(wù)器已經(jīng)啟動(dòng)。
(4)使用 process.on 方法監(jiān)聽(tīng)來(lái)自父進(jìn)程的消息。當(dāng)收到名為 "refresh" 的消息時(shí),回調(diào)函數(shù)將被觸發(fā)。
(5)在回調(diào)函數(shù)中,我們可以執(zhí)行資源重新加載或其他刷新操作。一般是做頁(yè)面的刷新操作。
server.js 創(chuàng)建了一個(gè)簡(jiǎn)單的 HTTP 服務(wù)器。當(dāng)有請(qǐng)求到達(dá)時(shí),服務(wù)器會(huì)返回 "offer get!!!" 的文本響應(yīng)。它還與父進(jìn)程進(jìn)行通信,當(dāng)收到名為 "refresh" 的消息時(shí),會(huì)執(zhí)行資源重新加載操作。
watcher.js
const fs = require("fs");
const { fork } = require("child_process");
let childProcess = null;
const watchFile = (filePath, callback) => {
fs.watch(filePath, (event) => {
if (event === "change") {
console.log("文件已經(jīng)被修改,重新加載");
// 如果之前的子進(jìn)程存在,終止該子進(jìn)程
childProcess && childProcess.kill();
// 創(chuàng)建新的子進(jìn)程
childProcess = fork(filePath);
childProcess.on("message", callback);
}
});
};
const startServer = (filePath) => {
// 創(chuàng)建一個(gè)子進(jìn)程,啟動(dòng)服務(wù)器
childProcess = fork(filePath);
childProcess.on("message", () => {
console.log("服務(wù)已啟動(dòng)!");
// 監(jiān)聽(tīng)文件變化
watchFile(filePath, () => {
console.log("文件已被修改");
});
});
};
// 注意文件的相對(duì)位置
startServer("./server.js");watcher.js 是一個(gè)用于監(jiān)視文件變化并自動(dòng)重新啟動(dòng)服務(wù)器的腳本。
(1)首先,引入 fs 模塊和 child_process 的 fork 方法,fork 方法是 Node.js 中 child_process 模塊提供的一個(gè)函數(shù),用于創(chuàng)建一個(gè)新的子進(jìn)程,通過(guò)調(diào)用 fork 方法,可以在主進(jìn)程中創(chuàng)建一個(gè)全新的子進(jìn)程,該子進(jìn)程可以獨(dú)立地執(zhí)行某個(gè)腳本文件。
(2)watchFile 函數(shù)用于監(jiān)視指定文件的變化。當(dāng)文件發(fā)生變化時(shí),會(huì)觸發(fā)回調(diào)函數(shù)。
(3)startServer 函數(shù)負(fù)責(zé)啟動(dòng)服務(wù)器。它會(huì)創(chuàng)建一個(gè)子進(jìn)程,并以指定的文件作為腳本運(yùn)行。子進(jìn)程將監(jiān)聽(tīng)來(lái)自 server.js 的消息。
(4)在 startServer 函數(shù)中,首先創(chuàng)建了一個(gè)子進(jìn)程來(lái)啟動(dòng)服務(wù)器并發(fā)送一個(gè)消息表示服務(wù)器已啟動(dòng)。
(5)然后,通過(guò)調(diào)用 watchFile 函數(shù),開(kāi)始監(jiān)聽(tīng)指定的文件變化。當(dāng)文件發(fā)生變化時(shí),會(huì)觸發(fā)回調(diào)函數(shù)。
(6)回調(diào)函數(shù)中,會(huì)終止之前的子進(jìn)程(如果存在),然后創(chuàng)建一個(gè)新的子進(jìn)程,重新運(yùn)行 server.js。
watcher.js 負(fù)責(zé)監(jiān)視特定文件的變化,并在文件發(fā)生變化時(shí)自動(dòng)重新啟動(dòng)服務(wù)器。它使用 child_process 模塊創(chuàng)建子進(jìn)程來(lái)運(yùn)行 server.js,并在需要重新啟動(dòng)服務(wù)器時(shí)終止舊的子進(jìn)程并創(chuàng)建新的子進(jìn)程。這樣就可以實(shí)現(xiàn)服務(wù)器的熱更新,當(dāng)代碼發(fā)生變化時(shí),無(wú)需手動(dòng)重啟服務(wù)器,watcher.js 將自動(dòng)處理這個(gè)過(guò)程。
效果圖
打開(kāi)本地的 7777 端口,看到了 'offet get!!!' 的初始字樣

當(dāng)修改了響應(yīng)文字時(shí),刷新頁(yè)面,無(wú)需重啟服務(wù),也能看到更新的字樣!

到此這篇關(guān)于使用JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)易的熱更新的文章就介紹到這了,更多相關(guān)JavaScript熱更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript結(jié)合Bootstrap仿微信后臺(tái)多圖文界面管理
這篇文章主要為大家詳細(xì)介紹了js結(jié)合Bootstrap仿微信后臺(tái)多圖文界面管理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
layui實(shí)現(xiàn)數(shù)據(jù)表格隱藏列的示例
今天小編就為大家分享一篇layui實(shí)現(xiàn)數(shù)據(jù)表格隱藏列的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10
全面解析Bootstrap中scrollspy(滾動(dòng)監(jiān)聽(tīng))的使用方法
這篇文章主要為大家全面解析Bootstrap中scrollspy(滾動(dòng)偵聽(tīng))的使用方法,感興趣的小伙伴們可以參考一下2016-06-06
JS實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能
本文主要介紹了JS實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能的步驟方法,可兼容所有PC瀏覽器,不兼容手機(jī)端。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02
MATLAB中fillmissing函數(shù)用法小結(jié)
這篇文章主要介紹了MATLAB中fillmissing函數(shù)用法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
NodeJS Express框架中處理404頁(yè)面一個(gè)方式
這篇文章主要介紹了NodeJS Express框架中處理404頁(yè)面一個(gè)方式,原理就是把404路由放在最后匹配,也就是路由中沒(méi)有定義的全部轉(zhuǎn)到404頁(yè)面,需要的朋友可以參考下2014-05-05

