前端缓存-- SPA项目静态资源缓存最佳实践方案

219 阅读3分钟

一、哈希指纹 + 长期缓存(推荐方案)

实现方式

# Nginx配置
location /static {
  add_header Cache-Control "public, max-age=31536000, immutable";
}

工作原理

  • 构建工具生成带哈希的文件名:main.abc123.js
  • 通过immutable声明文件内容永不改变

优点

  1. 最高缓存命中率(100%)
  2. 零协商请求(直接使用本地缓存)
  3. 完美解决更新问题(文件名变化即更新)

缺点

  1. 需要构建工具支持(Webpack/Vite/Rollup)
  2. 首次加载无缓存时需下载全量资源

适用场景

  • 现代前端工程化项目
  • 频繁更新的业务代码

二、版本化路径方案

实现方式

<script src="/v1.2.3/js/main.js"></script>

工作原理

  • 通过路径版本号控制缓存
  • 版本更新时路径变化

优点

  1. 人工控制缓存更新时机
  2. 便于多版本共存
  3. 兼容性极佳(无需特殊header)

缺点

  1. 版本管理成本高
  2. 存在冗余文件(旧版本资源)
  3. 缓存粒度粗(整个版本资源同时失效)

适用场景

  • 第三方库资源托管
  • 需要长期维护多版本的系统

三、查询字符串版本控制

实现方式

<script src="/js/main.js?v=1.2.3"></script>

工作原理

  • 通过URL参数标识版本
  • 参数变化时触发重新下载

优点

  1. 实现简单(无需构建工具)
  2. 快速部署生效

缺点

  1. 部分CDN会忽略查询参数
  2. 代理服务器可能不缓存带参URL
  3. 缓存可靠性低(30%的缓存失效风险)

适用场景

  • 临时热修复
  • 小规模静态网站

四、Service Worker缓存

实现方式

// sw.js
self.addEventListener('install', e => {
  e.waitUntil(
    caches.open('v1').then(cache => 
      cache.addAll(['/main.css', '/app.js']))
  );
});

工作原理

  • 通过JavaScript控制缓存策略
  • 支持精细化的缓存管理

优点

  1. 完全控制缓存逻辑
  2. 支持离线访问
  3. 可实现渐进式更新

缺点

  1. 实现复杂度高
  2. 需要处理版本迁移
  3. 首次加载需要注册SW

适用场景

  • PWA应用
  • 对离线能力有要求的场景

五、CDN边缘缓存

实现方式

# CDN配置
Cache-Control: public, max-age=86400
Edge-Control: max-age=3600

工作原理

  • 利用CDN节点的边缘缓存
  • 分层控制缓存策略

优点

  1. 减少源站压力
  2. 全球加速访问
  3. 支持动态调整TTL

缺点

  1. 配置依赖CDN厂商
  2. 清除缓存需要额外操作
  3. 成本较高

适用场景

  • 全球用户分布的业务
  • 大流量静态资源分发

六、协商缓存(ETag/Last-Modified)

实现方式

# Nginx默认配置
etag on;

工作原理

  • 通过304响应复用本地缓存
  • 每次请求需要校验新鲜度

优点

  1. 保证内容最新
  2. 节省带宽消耗

缺点

  1. 每次产生验证请求
  2. 延迟真实内容获取
  3. 服务器计算开销

适用场景

  • 频繁变更的小文件
  • 无法生成哈希的遗留系统

七、组合策略(最佳实践)

实现方案

graph TD
    A[核心代码] --> B[哈希指纹+immutable]
    C[第三方库] --> D[版本路径缓存]
    E[配置类文件] --> F[协商缓存]
    G[用户内容] --> H[CDN边缘缓存]

优势对比

策略缓存命中率更新及时性实现成本带宽消耗
哈希指纹★★★★★★★★★★★★★☆☆★☆☆☆☆
版本路径★★★☆☆★★☆☆☆★★☆☆☆★★★☆☆
查询字符串★★☆☆☆★★★☆☆★☆☆☆☆★★★★☆
Service Worker★★★★☆★★★★☆★★★★☆★★☆☆☆
CDN边缘缓存★★★★☆★★★☆☆★★★☆☆★☆☆☆☆
协商缓存☆☆☆☆☆★★★★★★☆☆☆☆★★★★☆

方案选择建议

  1. 新项目首选:哈希指纹 + CDN边缘缓存 + Service Worker
  2. 混合架构项目:核心代码用哈希指纹 + 第三方库用版本路径
  3. 遗留系统改造:逐步引入查询字符串版本 + 协商缓存
  4. 全球化业务:CDN边缘缓存 + 智能DNS解析

特殊场景处理

  1. A/B测试资源
# 根据Cookie分流
map $http_cookie $cache_key {
  default        "default";
  "abtest=new"   "v2";
}

location /static {
  proxy_cache_key "$cache_key-$uri";
}
  1. 大文件分片缓存
// 视频分片缓存策略
Range: bytes=0-1023
Accept-Ranges: bytes
Cache-Control: max-age=3600, public
  1. 动态字体加载
/* 字体加载策略 */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2');
  font-display: swap; /* 先显示备用字体 */
  unicode-range: U+000-5FF; /* 按需加载 */
}