摘要:
我翻了很多页面才确认:91网页版越用越顺的秘密:先把缓存管理做对(建议反复看)当一个网页版越用越卡,往往不是页面本身“偷懒”,而是缓存策略跟不上更新的节奏。翻了不少资料、亲自试验... 我翻了很多页面才确认:91网页版越用越顺的秘密:先把缓存管理做对(建议反复看)
当一个网页版越用越卡,往往不是页面本身“偷懒”,而是缓存策略跟不上更新的节奏。翻了不少资料、亲自试验和改进后,我把那些能让网页版长期顺畅、用户体验稳定的缓存管理方法整理成这篇可直接落地的指南。适合普通用户快速排查,也适合开发/运维在发布流程里套用的清单。
先说明核心结论(省时间)
- 静态资源(JS/CSS/图片)可以长时间缓存;核心 HTML(入口页面)必须能快速检查更新并拿到最新版本。
- 版本化(文件名带 hash 或 query-string)+ 正确的 Cache-Control 策略 = 最少的用户抱怨。
- 对于 PWA/Service Worker,要控制 SW 的更新策略,避免“新版本部署但旧壳一直被用着”的问题。
普通用户:遇到越用越卡时的快速自检(30 秒内)
- 强制刷新:Windows 上按 Ctrl+F5(或 Shift+刷新),Mac 上按 Command+Shift+R。
- 无痕/隐身模式打开页面,看是否顺畅(可以判断是否为缓存问题)。
- Chrome DevTools:F12 → Application → Clear storage → 勾选并清除;或在 Network 面板勾选“Disable cache”(仅在 DevTools 开启时生效)。
- 如果是手机,清除该应用或浏览器的缓存;或卸载/重装网页相关的 PWA。 这些操作可以快速判断是否为缓存导致的页面异常。
开发/运维:从服务器到浏览器的缓存策略(可复制的配置与原则) 1) 区分资源类型并分别设置策略
- index.html、app shell、登录页等:短缓存或 no-cache,确保浏览器每次请求时能检测到是否有新版本。 示例(Nginx): location = /index.html { add_header Cache-Control "no-cache, must-revalidate"; }
- 静态资源(带 hash 的 JS/CSS/图片/字体):长期缓存,配合文件名版本化。 示例(Nginx): location ~* .(js|css|png|jpg|svg|woff2)$ { add_header Cache-Control "public, max-age=31536000, immutable"; }
2) 资源版本化(最稳妥的缓存破坏方法)
- 内容哈希文件名:app.82b1f3.js、style.4a7d9c.css。每次构建输出不同的 hash。
- 如果无法改名,使用 query-string 版本号:app.js?v=20260219(不过某些 CDNs 可能配置不同,优先推荐哈希名)。
3) Cache-Control 与 ETag 的配合
- Cache-Control: public, max-age=31536000, immutable —— 对长期不变的资源。
- 对必须检查的文件使用 Cache-Control: no-cache 或 max-age=0, must-revalidate,让浏览器每次向服务器发起条件请求(If-None-Match/If-Modified-Since)。
- ETag / Last-Modified 可以减少带宽(304 Not Modified),但对大规模部署,优先靠哈希名来避免复杂的条件请求。
4) CDN 与缓存失效(Purge)策略
- 静态资源通过 CDN 分发后,部署新版本时要做 CDN 清理或使用版本化 URL 避免强制 purge。
- 如果必须 purge,请自动化:构建脚本结束后触发 CDN 的 API 清理对应路径。
5) Service Worker(PWA)常见坑与推荐策略
- 坑:SW 缓存了旧的 app shell,用户打开就是旧页面。
- 推荐:
- 将 service-worker.js 自带版本或 hash,SW 文件本身应短缓存,这样浏览器能尽快检测到新 SW。
- 在 SW 内部使用明确的 cache name(如 cache-v20260219),在 activate 生命周期清理旧缓存: self.addEventListener('activate', event => { const expected = ['cache-v20260219']; event.waitUntil( caches.keys().then(keys => Promise.all(keys.map(k => expected.includes(k) ? Promise.resolve() : caches.delete(k)))) ); self.clients.claim(); });
- 对 HTML 使用 network-first 策略(优先网络,失败回退缓存);对图片/字体使用 cache-first。
- 当新 SW 可用时,通知页面刷新或提供“点击更新”按钮,而不要自动强制刷新破坏用户正在进行的操作。
6) 本地存储(localStorage / IndexedDB)管理
- 不要把动态、易变的数据长期依赖 localStorage 为主副本;适合离线缓存且可恢复的场景才用。
- 版本化存储结构。每次应用升级时检查存储版本,必要时迁移或清理旧数据,避免数据格式错配导致的错误。
发布流程建议(把手动变成自动)
- 构建输出包含带 hash 的文件名。
- CI/CD 完成后自动更新 index.html(或模板)中的引用。
- 自动触发 CDN 的更新或把文件名哈希化以避免 purge。
- 将 service-worker.js 设置为快速有效期,确保浏览器能尽快检测到新 SW。
- 上线后监控误报:前端错误监控(Sentry /类似)与性能监控(Lighthouse/Real User Monitoring),及时捕捉因缓存策略导致的回归。
排查实战案例(简短) 场景:用户反馈登录后页面样式乱、功能异常。快速排查顺序: 1) 让用户强制刷新或使用隐身模式确认是否缓存问题。 2) 检查是否是新版 JS 没加载(network 面板看文件版本号/文件哈希)。 3) 若为 SW 问题,访问 /service-worker.js 看版本是否更新;可让用户清除站点数据或注销 SW(DevTools Application → Service Workers → Unregister)。 4) 根源通常是:HTML 没换、静态资源已换或 SW 缓存没更新。解决方法是让 index.html 不被长期缓存或让 SW 更快取得新版本。
部署后核对清单(发布当天用)
- [ ] index.html /入口文件设置为 no-cache 或短时缓存
- [ ] 静态资源采用文件名 hash,并设置长缓存
- [ ] 构建脚本输出的文件名已更新并被引用(检查 CDN 地址)
- [ ] service-worker.js 带版本并能清理旧 cache 名称
- [ ] CDN 的缓存策略与 purge 自动化到位
- [ ] 测试:强制刷新、隐身模式、不同设备浏览器均能拿到新版本

