缓存策略的核心是按资源特性分层控制:静态脚本用强缓存,动态数据用协商缓存或内存缓存,中间状态折中处理;Service Worker 实现离线优先与精准控制;内存缓存需设边界防污染;构建部署须同步缓存配置。

缓存策略的核心不是“全缓存”或“不缓存”,而是按资源特性分层控制:静态脚本追求极致加载速度,动态数据强调及时性,中间状态则需折中。关键在于把不同生命周期、更新频率和业务敏感度的资源,交给最适合的缓存机制来处理。
区分资源类型,匹配对应缓存层级
同一页面里的 JS 资源差异很大,不能一概而论:
-
框架与工具库(如 React、Lodash):内容稳定、体积大、复用率高 → 配置强缓存(
Cache-Control: public, max-age=31536000, immutable),配合文件名哈希确保版本更新时自动失效 -
业务逻辑 JS(如 app.js、feature.js):随发布频繁变更 → 使用协商缓存(
ETag或Last-Modified),让浏览器在每次请求时验证是否需要更新 - 运行时生成的数据(如用户配置、API 响应):可能随时变化 → 不走 HTTP 缓存,改用内存缓存(Map/Object)+ 明确的失效触发(如登录登出、表单提交后清除)
用 Service Worker 实现可控的离线优先策略
当需要兼顾速度与可控更新时,Service Worker 是最灵活的方案。它不依赖响应头,而是由代码显式决定缓存行为:
- 安装阶段预缓存核心脚本(
caches.open().addAll([...])),保证首次离线也能运行 - fetch 事件中优先返回缓存,但对特定路径(如
/api/)跳过缓存直接发请求,保障数据实时性 - 更新时通过版本号切换缓存空间(如
CACHE_NAME = 'js-v2'),旧缓存可保留到新 SW 激活后再清理,避免白屏
内存缓存要设边界,避免“缓存污染”
函数级记忆化(memoization)或 Map 存储 API 结果虽快,但若无约束会拖慢长期运行的应用:
立即学习“Java免费学习笔记(深入)”;
- 为内存缓存设置数量上限(如 LRU 算法),或时间窗口(
setTimeout清除过期项) - 对敏感操作(如支付、库存查询)禁用缓存,或强制加
cache: 'no-store'请求选项 - 避免缓存整个响应对象(含未序列化的函数、DOM 引用),只存结构化数据(JSON-safe)
构建与部署环节必须同步缓存策略
再好的客户端缓存,也会被错误的构建方式破坏:
- JS 文件名带 contenthash(如
app.a1b2c3.js),配合Cache-Control: max-age=31536000,既享受长期缓存,又杜绝旧版本残留 - HTML 文件本身禁用强缓存(
Cache-Control: no-cache),确保用户总能拿到最新资源清单 - CDN 或反向代理上配置一致的缓存头,避免中间节点覆盖或忽略原始响应头


















