一、哈希指纹 + 长期缓存(推荐方案)
实现方式:
# Nginx配置
location /static {
add_header Cache-Control "public, max-age=31536000, immutable";
}
工作原理:
- 构建工具生成带哈希的文件名:
main.abc123.js - 通过
immutable声明文件内容永不改变
优点:
- 最高缓存命中率(100%)
- 零协商请求(直接使用本地缓存)
- 完美解决更新问题(文件名变化即更新)
缺点:
- 需要构建工具支持(Webpack/Vite/Rollup)
- 首次加载无缓存时需下载全量资源
适用场景:
- 现代前端工程化项目
- 频繁更新的业务代码
二、版本化路径方案
实现方式:
<script src="/v1.2.3/js/main.js"></script>
工作原理:
- 通过路径版本号控制缓存
- 版本更新时路径变化
优点:
- 人工控制缓存更新时机
- 便于多版本共存
- 兼容性极佳(无需特殊header)
缺点:
- 版本管理成本高
- 存在冗余文件(旧版本资源)
- 缓存粒度粗(整个版本资源同时失效)
适用场景:
- 第三方库资源托管
- 需要长期维护多版本的系统
三、查询字符串版本控制
实现方式:
<script src="/js/main.js?v=1.2.3"></script>
工作原理:
- 通过URL参数标识版本
- 参数变化时触发重新下载
优点:
- 实现简单(无需构建工具)
- 快速部署生效
缺点:
- 部分CDN会忽略查询参数
- 代理服务器可能不缓存带参URL
- 缓存可靠性低(30%的缓存失效风险)
适用场景:
- 临时热修复
- 小规模静态网站
四、Service Worker缓存
实现方式:
// sw.js
self.addEventListener('install', e => {
e.waitUntil(
caches.open('v1').then(cache =>
cache.addAll(['/main.css', '/app.js']))
);
});
工作原理:
- 通过JavaScript控制缓存策略
- 支持精细化的缓存管理
优点:
- 完全控制缓存逻辑
- 支持离线访问
- 可实现渐进式更新
缺点:
- 实现复杂度高
- 需要处理版本迁移
- 首次加载需要注册SW
适用场景:
- PWA应用
- 对离线能力有要求的场景
五、CDN边缘缓存
实现方式:
# CDN配置
Cache-Control: public, max-age=86400
Edge-Control: max-age=3600
工作原理:
- 利用CDN节点的边缘缓存
- 分层控制缓存策略
优点:
- 减少源站压力
- 全球加速访问
- 支持动态调整TTL
缺点:
- 配置依赖CDN厂商
- 清除缓存需要额外操作
- 成本较高
适用场景:
- 全球用户分布的业务
- 大流量静态资源分发
六、协商缓存(ETag/Last-Modified)
实现方式:
# Nginx默认配置
etag on;
工作原理:
- 通过304响应复用本地缓存
- 每次请求需要校验新鲜度
优点:
- 保证内容最新
- 节省带宽消耗
缺点:
- 每次产生验证请求
- 延迟真实内容获取
- 服务器计算开销
适用场景:
- 频繁变更的小文件
- 无法生成哈希的遗留系统
七、组合策略(最佳实践)
实现方案:
graph TD
A[核心代码] --> B[哈希指纹+immutable]
C[第三方库] --> D[版本路径缓存]
E[配置类文件] --> F[协商缓存]
G[用户内容] --> H[CDN边缘缓存]
优势对比:
| 策略 | 缓存命中率 | 更新及时性 | 实现成本 | 带宽消耗 |
|---|---|---|---|---|
| 哈希指纹 | ★★★★★ | ★★★★★ | ★★★☆☆ | ★☆☆☆☆ |
| 版本路径 | ★★★☆☆ | ★★☆☆☆ | ★★☆☆☆ | ★★★☆☆ |
| 查询字符串 | ★★☆☆☆ | ★★★☆☆ | ★☆☆☆☆ | ★★★★☆ |
| Service Worker | ★★★★☆ | ★★★★☆ | ★★★★☆ | ★★☆☆☆ |
| CDN边缘缓存 | ★★★★☆ | ★★★☆☆ | ★★★☆☆ | ★☆☆☆☆ |
| 协商缓存 | ☆☆☆☆☆ | ★★★★★ | ★☆☆☆☆ | ★★★★☆ |
方案选择建议
- 新项目首选:哈希指纹 + CDN边缘缓存 + Service Worker
- 混合架构项目:核心代码用哈希指纹 + 第三方库用版本路径
- 遗留系统改造:逐步引入查询字符串版本 + 协商缓存
- 全球化业务:CDN边缘缓存 + 智能DNS解析
特殊场景处理
- A/B测试资源:
# 根据Cookie分流
map $http_cookie $cache_key {
default "default";
"abtest=new" "v2";
}
location /static {
proxy_cache_key "$cache_key-$uri";
}
- 大文件分片缓存:
// 视频分片缓存策略
Range: bytes=0-1023
Accept-Ranges: bytes
Cache-Control: max-age=3600, public
- 动态字体加载:
/* 字体加载策略 */
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap; /* 先显示备用字体 */
unicode-range: U+000-5FF; /* 按需加载 */
}