You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Service Worker缓存脚本加载旧数据:除提示刷新外的解决方案咨询

解决异步加载JSON时缓存不匹配导致的404问题

这个场景我太熟悉了——打包后的资源带哈希后缀,旧缓存的脚本还在找旧文件名的JSON,结果触发404。除了弹出提示让用户刷新,还有几个更平滑的方案,能减少用户感知甚至完全无感知:

1. 版本化资源清单(Manifest)

构建时生成一个包含所有资源哈希路径的manifest.json,应用启动先拉取这个清单,对比本地缓存的版本,确认资源路径后再加载JSON。这样不管脚本是不是旧的,都能拿到最新的资源路径。

示例代码:

// 应用初始化时先校验资源清单
async function initApp() {
  try {
    const remoteManifest = await fetch('/manifest.json').then(res => res.json());
    const localManifest = JSON.parse(localStorage.getItem('app-resource-manifest') || '{}');
    
    // 如果清单不一致,更新本地缓存的路径映射
    if (remoteManifest['data.json'] !== localManifest['data.json']) {
      localStorage.setItem('app-resource-manifest', JSON.stringify(remoteManifest));
    }

    // 用清单里的最新路径加载JSON
    const data = await import(`./assets/${remoteManifest['data.json']}.json`);
    renderApp(data.default);
  } catch (err) {
    // 兜底:加载默认的JSON或者提示用户
    console.error('加载资源失败', err);
  }
}

initApp();

注意:manifest.json本身要设置不缓存(服务器响应头Cache-Control: no-cache),不然用户会一直拿到旧清单。

2. 服务端Fallback机制

在服务器配置里,给JSON资源加一个兜底规则:当请求的旧哈希文件不存在时,直接返回最新版本的JSON。这样旧脚本即使请求了不存在的文件,也能拿到有效数据,用户完全无感知,等下次自然刷新就会加载新脚本了。

以Nginx为例,配置规则:

location ~* ^/assets/.*\.json$ {
    # 先尝试请求原路径,不存在就返回最新的JSON文件
    try_files $uri /assets/latest-data.json;
}

构建时记得把最新的JSON文件同时复制一份为latest-data.json,或者用构建工具自动同步这个文件。

3. 后台预加载+无缝切换

当检测到版本更新时,不立即打扰用户,而是在后台悄悄加载新的脚本和资源,等用户进行下一次主动操作(比如切换页面、点击按钮)时,无缝切换到新版本。

示例思路:

let hasNewVersion = false;
let newAppEntry = null;
let remoteVersion = '';

// 检测版本更新
async function checkForUpdate() {
  const currentVersion = localStorage.getItem('app-version') || 'initial';
  remoteVersion = await fetch('/version.txt').then(res => res.text().trim());

  if (remoteVersion !== currentVersion) {
    hasNewVersion = true;
    // 后台加载新的入口脚本
    const script = document.createElement('script');
    script.src = `/app.${remoteVersion}.js`;
    script.onload = () => {
      // 新脚本加载完成后,暴露初始化方法
      newAppEntry = window.initNewApp;
      // 可以给个轻量提示,比如右上角小徽章“有更新,点击生效”
      showUpdateBadge();
    };
    document.body.appendChild(script);
  }
}

// 用户操作时触发切换
document.addEventListener('click', (e) => {
  if (hasNewVersion && newAppEntry) {
    // 销毁当前旧应用实例
    destroyCurrentApp();
    // 初始化新应用
    newAppEntry();
    // 更新本地版本标记
    localStorage.setItem('app-version', remoteVersion);
    hasNewVersion = false;
    hideUpdateBadge();
  }
});

// 页面加载时启动版本检测
checkForUpdate();

4. Service Worker精准缓存控制

用Service Worker拦截所有资源请求,当请求的JSON文件404时,自动 fallback 到最新版本,或者提前缓存新版本资源。

Service Worker示例代码:

self.addEventListener('fetch', (event) => {
  const requestUrl = new URL(event.request.url);
  
  // 只处理JSON资源请求
  if (requestUrl.pathname.endsWith('.json')) {
    event.respondWith(
      fetch(event.request)
        .catch(async () => {
          // 请求失败,返回最新的JSON资源
          return await fetch('/assets/latest-data.json');
        })
    );
  }
});

这种方案适合PWA应用,能做到完全无感知的资源容错。


内容的提问来源于stack exchange,提问作者Timo Jokinen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:24:49