面试官最喜欢问的:前端怎么自动检测代码更新?

在前端开发中,我们通常会使用打包工具(如 Vite、Webpack)将 JS/CSS 等资源构建上线,并配合 CDN、浏览器缓存来加速访问。但问题也随之而来:

"我已经发布新版本了,怎么用户还看到旧界面?"

"为啥修复的 bug 还在?"

原因很简单:用户浏览器缓存了旧的静态资源,没有感知新版本的变更。

🎯 目标:前端页面如何自动检测打包更新并提示刷新

关键需求是:

  • 服务器发布了新版本,客户端能"感知"到。
  • 最好不依赖后端数据库或额外接口。
  • 弹窗或强制刷新,提示用户更新。

思考:为啥不直接加 hash?

其实我们打包时已经使用 [hash] 命名资源了,那为啥还要检测更新?

因为:

  • 浏览器对 HTML 本身不会缓存 bust;
  • 页面里写死了旧的 <script src="/main.abcd.js">,不会自动拉新版;
  • 用户长时间不刷新页面就不会拉取新 HTML,自然也没拉到新版 JS。

所以必须在 运行中的前端代码层面 进行更新感知。

方案一:轮询版本文件(最常用)

实现思路:

  1. 打包时生成一个版本文件(如 version.json 或注入 index.html 里的 __BUILD_VERSION__ 字段);
  2. 页面加载后,定时轮询该文件;
  3. 一旦检测到版本变更(比如哈希不同),提示用户刷新。

示例代码:

typescript 复制代码
const CURRENT_VERSION = __BUILD_VERSION__; // 构建时注入变量

setInterval(() => {
  fetch('/version.json?t=' + Date.now())
    .then(res => res.json())
    .then(({ version }) => {
      if (version !== CURRENT_VERSION) {
        alert('检测到新版本,点击确定刷新页面');
        window.location.reload(true);
      }
    });
}, 10000); // 每 10 秒轮询一次

或者使用文件指纹思路:

  1. 打包后生成一个 manifest 文件 (比如 asset-manifest.jsonmeta.json),里面记录资源及其 hash;

  2. 页面运行时轮询这个 manifest 文件;

  3. 如果发现文件名或 hash 有变,提示刷新页面。

在 Vite 中添加如下配置:

typescript 复制代码
// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  build: {
    manifest: true, // 开启 manifest 生成
  }
})

构建后会生成 dist/manifest.json,类似这样:

typescript 复制代码
{
  "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" }
}

前端代码(可封装成检测模块):

typescript 复制代码
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('🚨 发现新版本,准备刷新页面')
      alert('检测到新版本,点击确认刷新页面')
      window.location.reload(true)
    }
  } catch (err) {
    console.error('版本检查失败', err)
  }
}

setInterval(checkForUpdate, 10000) // 每 5 秒检查一次

💡manifest.json 中的文件路径含 hash,只要内容变,hash 就会变,就能准确识别版本是否更新。

优点:

  • 实现简单,支持所有现代浏览器;
  • 可手动控制提示逻辑,提升用户体验;
  • 和打包工具(Vite/Webpack)配合紧密。

缺点:

  • 本质上还是轮询,数据拉取有频率;
  • 如果用户挂着页面一整天,刷新前所有交互还是旧代码。

方案二:WebSocket(配合 CI/CD 或打包系统)

✅ 前提:

  • 服务端拥有 WebSocket 服务能力(如 Node.js + ws 模块);
  • 每次前端构建部署完成后,触发一次"更新通知"。

服务端(nodejs+ws模块):

js 复制代码
// 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' }));
    }
  }
}

// 模拟触发更新(实际应在构建完成后调用)
setTimeout(() => {
  console.log('🎉 New version released, notifying clients...');
  notifyClients();
}, 10000); // 10 秒后触发

如果你有配套的部署平台或打包平台(如 Jenkins、Vercel、Netlify),可以在部署成功后广播一条"版本已更新"的消息。

客户端建立 WebSocket 连接,一旦收到推送,就提示刷新页面。

js 复制代码
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 插件等。

优点:

  • 实时;
  • 可以配合更多更新逻辑(如强制下线);

缺点:

  • 成本高,依赖后端支持,对于检测更新的需求一般无需这么实时;
  • 不适合资源有限的小项目;

总结

前端页面检测更新并不是"有没有后端通知",而是我们主动地检测自己的版本是否已经被 CDN 或打包平台更新轮询 version.json 是最稳定、兼容性最强的方案; WebSocket 通知 是顶配方案,适合重型系统。

相关推荐
恋猫de小郭3 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment11 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端