基于指纹文件名的前端版本更新与缓存策略实践

124 阅读3分钟

为什么“指纹文件名”能触发更新

  • 原理:构建产物的 .js/.css 文件名里包含内容哈希(如 index-CGIWmfc8.js)。只要代码变更,哈希就变,新文件名也变。
  • 流程
    1. 浏览器先请求 index.html
    2. index.html 内引用了带新哈希的资源 URL;
    3. 浏览器发现是“从未见过”的新文件名,必然重新下载新资源(不会命中旧缓存)。
  • 关键点:要让浏览器“拿到最新的 index.html”,否则它就不知道有新的哈希文件名。

为什么 HTML 建议 no-cache,而静态资源建议长缓存

  • HTML(入口)
    • 作用:它是“目录索引”,负责告诉浏览器最新的资源文件名。
    • 策略:设置 Cache-Control 为 “no-cache” 或者“短缓存 + ETag/Last-Modified”,让浏览器每次(或很快)向服务器验证新旧。
    • 含义:no-cache 不是“不缓存”,而是“每次用前先和服务器确认是否有更新”(条件请求,命中则 304)。
  • 静态资源(.js/.css/字体/图片)
    • 作用:体积大、数量多;文件名带哈希,内容变更才会换名。
    • 策略:可设置超长缓存,如 1 年,并加 immutable。因为一旦内容变更,文件名会变,不会与旧缓存冲突。
    • 好处:加速加载、减少带宽与服务器压力。

Nginx 实践配置 示例

  • HTML:启用协商缓存,或直接 no-cache
# 根路径或 HTML
location = / {
    add_header Cache-Control "no-cache";
    # 或者短缓存 + must-revalidate
    # add_header Cache-Control "max-age=60, must-revalidate";
}

location ~* \.html$ {
    add_header Cache-Control "no-cache";
    # 可选:确保有 ETag/Last-Modified,nginx 默认发送 Last-Modified
    # etag on;  #(多数版本默认开启,可视版本情况)
}
  • 静态资源:长缓存 + immutable(仅对带哈希命名的产物生效)
# 带哈希产物所在目录(按你的部署路径调整)
location /assets/ {
    # 强缓存 1 年
    expires 1y;
    add_header Cache-Control "public, max-age=31536000, immutable";
    # 确保不对这些资源做额外改写
    try_files $uri =404;
}
  • 注意:如果你的静态资源不带哈希(如某些图片),不要给它们设置 immutable 的超长缓存,否则更新会困难。

可替代/补充策略

  • 严格不缓存 HTMLCache-Control: no-store(最保守,次次强制获取最新 HTML;代价是请求次数更多)。
  • 短缓存 HTMLCache-Control: max-age=60, must-revalidate(1 分钟内直接用,过期后协商校验;兼顾性能与时效)。
  • CDN/代理一致性:CDN 也要对路径类型分别配置缓存策略,避免覆盖源站策略。

如何验证

  • 用 curl 看响应头是否符合预期:
# HTML
curl -I https://你的域名/index.html

# 某个构建后的 js/css
curl -I https://你的域名/assets/index-CGIWmfc8.js
  • 在浏览器 DevTools → Network:
    • 刷新页面,查看 index.html 是否显示 from disk cache/from memory cachestatus 304(命中协商缓存)。
    • 查看 .js/.css 是否带 Cache-Control: public, max-age=31536000, immutable
  • 发布新版本后:
    • index.html 应该很快拿到新内容(或经验证返回 304 未改动)。
    • 引用的资源文件名变了,浏览器会请求新 .js/.css 文件,完成更新。

常见坑

  • HTML 被意外长缓存:用户一直拿不到最新 index.html,看不到新文件名,导致前端不更新。
  • 静态资源没用哈希命名:即便文件内容变了,文件名不变,长缓存会让用户继续用老资源。
  • CDN 覆盖源策略:CDN 把 HTML 也长缓存了,发布后用户仍拿旧 HTML。

这样配置后,发布新版本时只要替换 index.html 与新指纹资源,浏览器就会在下一次刷新或访问时感知到新版本并拉取新资源,既保证时效,又保证性能。