静态资源缓存配置实操:从改配置到验证生效
静态资源加载慢是站点运营中最常见的问题之一。用户打开页面时,图片、CSS、JS 文件如果每次都从服务器重新拉取,不仅拖慢首屏时间,还会增加服务器负担。但很多站长不敢开缓存,核心顾虑是:文件更新后,用户浏览器还在用旧版本,导致样式错乱或功能异常。本文从实操角度给出一套可复现的做法,让你在不引入额外工具的前提下,用最短时间把静态资源缓存配好并验证生效。
先分清两类文件:稳定型与频繁变更型
配置缓存的第一步不是直接改 Cache-Control,而是先把站点里的静态资源按变更频率分成两类。第一类是稳定型文件,比如 logo、图标、字体文件、基础样式表,这类文件内容很少变化,一旦发布就长期有效。第二类是频繁变更型文件,比如业务逻辑 JS、活动页样式、经常调整的图片素材,这类文件可能每周甚至每天更新。
分类的依据很简单:打开你的站点源码目录,看每个文件的修改时间。如果一个文件最近三个月都没动过,它就是稳定型;如果最近一个月内修改过两次以上,它就是频繁变更型。这个分类动作不需要任何工具,用文件管理器或命令行 ls -l 就能完成。把两类文件分别列出来,后面配置时就不会一刀切。
稳定型文件:长缓存加版本号
对于稳定型文件,策略是给一个很长的 max-age,同时在文件名或查询参数里嵌入版本号。具体做法是:在 HTML 引用这些文件时,把文件名改成带哈希的形式,比如 style.3a7b2c.css、logo.v2.png。哈希值可以用文件内容的 MD5 前六位生成,很多构建工具(Webpack、Vite)都内置了这个功能,开启后会自动处理。
如果你没有构建工具,手动操作也不复杂:用命令行 md5sum style.css 拿到哈希值,然后把文件重命名为 style.哈希值.css,再更新 HTML 里的引用路径。服务器端配置上,给这类带哈希的文件设置 Cache-Control: max-age=31536000, immutable。immutable 告诉浏览器这个文件一年内不会变,不要发任何协商请求。
为什么要在文件名里加版本号?因为当文件内容变化时,哈希值跟着变,文件名也就变了,浏览器会把它当作全新资源重新请求,旧文件自然不会被使用。这样既享受了长缓存的速度优势,又避免了更新后看到旧版本的问题。
频繁变更型文件:短缓存加 ETag
对于频繁变更型文件,策略反过来:给一个较短的 max-age,同时启用 ETag 做协商缓存。服务器配置上设置 Cache-Control: max-age=300, must-revalidate,表示文件在浏览器最多缓存 5 分钟,过期后必须回服务器验证。ETag 是服务器为每个文件生成的唯一标识符,通常是文件内容或修改时间的哈希。
当浏览器再次请求这个文件时,会带上 If-None-Match 头,值是上次拿到的 ETag。服务器收到后对比当前文件的 ETag,如果没变就返回 304 Not Modified,不传文件内容,节省带宽;如果变了就返回 200 和新文件。这样即使文件频繁更新,用户也能在 5 分钟内拿到最新版本,同时避免了每次都下载完整文件。
大多数 Web 服务器默认开启 ETag,你不需要额外写代码。Nginx 和 Apache 都自带这个功能,只要确保没有在配置里关掉它。验证方法是在浏览器开发者工具的 Network 面板里看请求头,如果看到 If-None-Match 和响应头里有 ETag,说明协商缓存在工作。
配置完成后如何验证生效
改完配置最怕的是不确定是否生效。这里给出一套验证流程,不需要任何付费工具。第一步,打开浏览器开发者工具,切到 Network 面板,勾选 Disable cache 旁边的选项取消勾选,确保浏览器会走缓存。第二步,刷新页面,看静态资源的 Size 列:如果显示 from disk cache 或 from memory cache,说明浏览器用了本地缓存;如果显示 304,说明协商缓存生效;如果显示 200 且 Size 是完整文件大小,说明缓存没命中。
第三步,用 curl 命令直接验证服务器配置。在终端输入 curl -I https://你的域名/style.3a7b2c.css,看返回头里的 Cache-Control 和 ETag 字段是否符合预期。如果 Cache-Control 显示 max-age=31536000, immutable,说明稳定型文件配置正确;如果显示 max-age=300, must-revalidate 且有 ETag,说明频繁变更型文件配置正确。
第四步,做一次实际更新测试。随便改一个稳定型文件的内容,重新生成哈希值并更新 HTML 引用,然后刷新页面。如果新样式立即生效,说明版本号机制工作正常。对于频繁变更型文件,改完内容后等 5 分钟刷新,应该能看到最新内容;如果没到 5 分钟就刷新,可能还是旧的,这是正常的,因为 max-age 还没过期。
常见失误与规避
第一个常见失误是给所有文件统一设置长缓存,没有区分稳定型和频繁变更型。结果就是更新 JS 后用户还在用旧版本,排查半天才发现是缓存没清理。规避方法是严格按前面的分类来做,稳定型走长缓存加版本号,频繁变更型走短缓存加 ETag。
第二个失误是开了长缓存但忘记加版本号。文件内容变了,但文件名没变,浏览器认为还是同一个文件,继续用旧缓存。规避方法是在构建流程里自动加哈希,或者每次发布前手动检查文件名是否更新。
第三个失误是配置改完没有重启服务器或清除 CDN 缓存。Nginx 改完配置要执行 nginx -s reload,Apache 要执行 systemctl restart apache2。如果前面有 CDN,还要去 CDN 控制台刷新缓存。很多人以为改完配置文件就生效了,结果等半天发现没变化,其实是服务没重载。
第四个失误是只看浏览器开发者工具,没有用 curl 验证服务器实际返回头。浏览器可能因为本地缓存策略不同,显示的结果和服务器真实配置不一致。curl 直接请求服务器,拿到的是第一手数据,更可靠。养成用 curl 验证的习惯,能省掉很多排查时间。