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