面試官最喜歡問的題目之前端怎么自動檢測代碼更新
在前端開發(fā)中,我們通常會使用打包工具(如 Vite、Webpack)將 JS/CSS 等資源構(gòu)建上線,并配合 CDN、瀏覽器緩存來加速訪問。但問題也隨之而來:
“我已經(jīng)發(fā)布新版本了,怎么用戶還看到舊界面?”
“為啥修復的 bug 還在?”
原因很簡單:用戶瀏覽器緩存了舊的靜態(tài)資源,沒有感知新版本的變更。
?? 目標:前端頁面如何自動檢測打包更新并提示刷新
關鍵需求是:
- 服務器發(fā)布了新版本,客戶端能“感知”到。
- 最好不依賴后端數(shù)據(jù)庫或額外接口。
- 彈窗或強制刷新,提示用戶更新。
思考:為啥不直接加 hash?
其實我們打包時已經(jīng)使用 [hash] 命名資源了,那為啥還要檢測更新?
因為:
- 瀏覽器對 HTML 本身不會緩存 bust;
- 頁面里寫死了舊的
<script src="/main.abcd.js">,不會自動拉新版; - 用戶長時間不刷新頁面就不會拉取新 HTML,自然也沒拉到新版 JS。
所以必須在 運行中的前端代碼層面 進行更新感知。
方案一:輪詢版本文件(最常用)
實現(xiàn)思路:
- 打包時生成一個版本文件(如
version.json或注入index.html里的__BUILD_VERSION__字段); - 頁面加載后,定時輪詢該文件;
- 一旦檢測到版本變更(比如哈希不同),提示用戶刷新。
示例代碼:
const CURRENT_VERSION = __BUILD_VERSION__; // 構(gòu)建時注入變量
setInterval(() => {
fetch('/version.json?t=' + Date.now())
.then(res => res.json())
.then(({ version }) => {
if (version !== CURRENT_VERSION) {
alert('檢測到新版本,點擊確定刷新頁面');
window.location.reload(true);
}
});
}, 10000); // 每 10 秒輪詢一次
或者使用文件指紋思路:
打包后生成一個 manifest 文件(比如
asset-manifest.json或meta.json),里面記錄資源及其 hash;頁面運行時輪詢這個 manifest 文件;
如果發(fā)現(xiàn)文件名或 hash 有變,提示刷新頁面。
在 Vite 中添加如下配置:
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
build: {
manifest: true, // 開啟 manifest 生成
}
})
構(gòu)建后會生成 dist/manifest.json,類似這樣:
{
"index.html": { "file": "index.html", "isEntry": true },
"src/main.ts": { "file": "assets/main.abc123.js", "isEntry": true },
"src/style.css": { "file": "assets/style.def456.css" }
}
前端代碼(可封裝成檢測模塊):
let currentVersionHash = ''
function getHashFromManifest(manifest: any): string {
// 自定義 hash 生成方式:可拼接所有文件路徑,也可只取主入口
return Object.values(manifest)
.map((entry: any) => entry.file)
.join('|')
}
async function checkForUpdate() {
try {
const res = await fetch(`/manifest.json?_t=${Date.now()}`)
const manifest = await res.json()
const newHash = getHashFromManifest(manifest)
if (!currentVersionHash) {
currentVersionHash = newHash
} else if (currentVersionHash !== newHash) {
console.log('?? 發(fā)現(xiàn)新版本,準備刷新頁面')
alert('檢測到新版本,點擊確認刷新頁面')
window.location.reload(true)
}
} catch (err) {
console.error('版本檢查失敗', err)
}
}
setInterval(checkForUpdate, 10000) // 每 5 秒檢查一次
??
manifest.json中的文件路徑含 hash,只要內(nèi)容變,hash 就會變,就能準確識別版本是否更新。
優(yōu)點:
- 實現(xiàn)簡單,支持所有現(xiàn)代瀏覽器;
- 可手動控制提示邏輯,提升用戶體驗;
- 和打包工具(Vite/Webpack)配合緊密。
缺點:
- 本質(zhì)上還是輪詢,數(shù)據(jù)拉取有頻率;
- 如果用戶掛著頁面一整天,刷新前所有交互還是舊代碼。
方案二:WebSocket(配合 CI/CD 或打包系統(tǒng))
? 前提:
- 服務端擁有 WebSocket 服務能力(如 Node.js +
ws模塊); - 每次前端構(gòu)建部署完成后,觸發(fā)一次“更新通知”。
服務端(nodejs+ws模塊):
// ws-server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const clients = new Set();
wss.on('connection', (ws) => {
console.log('?? New client connected');
clients.add(ws);
ws.on('close', () => {
clients.delete(ws);
});
});
// 通知所有客戶端刷新頁面
function notifyClients() {
for (let client of clients) {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({ type: 'update', message: 'new-version' }));
}
}
}
// 模擬觸發(fā)更新(實際應在構(gòu)建完成后調(diào)用)
setTimeout(() => {
console.log('?? New version released, notifying clients...');
notifyClients();
}, 10000); // 10 秒后觸發(fā)
如果你有配套的部署平臺或打包平臺(如 Jenkins、Vercel、Netlify),可以在部署成功后廣播一條“版本已更新”的消息。
客戶端建立 WebSocket 連接,一旦收到推送,就提示刷新頁面。
if ('WebSocket' in window) {
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
console.log('[WS] Connected to update server');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'update') {
console.log('[WS] New version detected');
// 這里可以是彈窗提醒,或者直接刷新
if (confirm('檢測到新版本,是否立即刷新頁面?')) {
window.location.reload();
}
}
};
ws.onclose = () => {
console.log('[WS] Connection closed');
};
ws.onerror = (err) => {
console.error('[WS] Error:', err);
};
}
可封裝為插件或獨立模塊進行復用,比如 Vue 插件、React Hook、Vite 插件等。
優(yōu)點:
- 實時;
- 可以配合更多更新邏輯(如強制下線);
缺點:
- 成本高,依賴后端支持,對于檢測更新的需求一般無需這么實時;
- 不適合資源有限的小項目;
總結(jié)
前端頁面檢測更新并不是“有沒有后端通知”,而是我們主動地檢測自己的版本是否已經(jīng)被 CDN 或打包平臺更新。 輪詢 version.json 是最穩(wěn)定、兼容性最強的方案; WebSocket 通知 是頂配方案,適合重型系統(tǒng)。
到此這篇關于面試官最喜歡問的題目之前端怎么自動檢測代碼更新的文章就介紹到這了,更多相關前端自動檢測代碼更新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript Date對象詳解及時間戳和時間的相互轉(zhuǎn)換問題
這篇文章主要介紹了JavaScript Date對象詳解及時間戳和時間的相互轉(zhuǎn)換問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01
詳解JavaScript對Date對象的操作問題(生成一個倒數(shù)7天的數(shù)組)
最近項目需求要生成一個倒數(shù)7天的數(shù)組,下面小編把我的實現(xiàn)思路和代碼整理分享給大家,供大家參考,需要的朋友可以參考下2015-10-10
JavaScript中window.sessionStorage的具體使用
window.sessionStorage是瀏覽器端臨時存儲數(shù)據(jù)的機制,僅在當前會話有效,支持鍵值對操作,下面就來介紹一下window.sessionStorage的具體使用,感興趣的可以了解一下2025-07-07
Node的優(yōu)勢我就不再亂吹捧了,它讓javascript統(tǒng)一web的前后臺成為了可能。但是對于新手來說,server端的JS代碼可能不像client端的代碼那么好調(diào)試,直觀。client端JS代碼的調(diào)試基本上經(jīng)歷了一個從“肉眼--alert()--firebug(或者其它的developer tools)”的一個過程。而對于server端的調(diào)試,可能新手仍然停留在使用“肉眼--console()”的階段。其實,Node經(jīng)過了這么多年(雖然才短短幾年)的發(fā)展,也有了很多不錯的第三方的調(diào)試工具。包括Node內(nèi)建的調(diào)試工具debugger、node-inspector等。2014-05-05
JavaScript中使用replace結(jié)合正則實現(xiàn)replaceAll的效果
JavaScript?中使用?replace?達到?replaceAll的效果,其實就用利用的正則的全局替換。2010-06-06
微信小程序?qū)崿F(xiàn)多選框全選與取消全選功能示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)多選框全選與取消全選功能,結(jié)合實例形式分析了微信小程序多選框功能實現(xiàn)、布局顯示及全選、取消全選相關操作技巧,需要的朋友可以參考下2019-05-05
uni-app彈出層uni-popup使用及修改默認樣式的方法實例
我們在使用uniapp開發(fā)的時候,有時可以使用uniapp自有的樣式模板,這樣可以提高開發(fā)效率,下面這篇文章主要給大家介紹了關于uni-app彈出層uni-popup使用及修改默認樣式的相關資料,需要的朋友可以參考下2022-11-11

