SEO 百科
缓存失效
本页目录
缓存失效
缓存失效 是让已经存下来的响应不再被当作可信内容,存它的那一层要么回源确认一次,要么直接放弃旧副本。站内有三条路:Cache-Control 管时间,ETag 管内容改没改,文件名带哈希让旧副本作废。三条路各省一段开销,代价也不在一起,选哪条要看资源多久改一次、旧内容多服务一会儿会带来什么后果。
时间与验证两条路
过期不等于丢弃。HTTP 有把旧副本变新的机制:客户端问一次源站,内容没变,本地这一份重新算作新鲜[1]。走这条路要在标头里写 no-cache,它要求每次使用之前先验证[1]。
没写 Cache-Control 的时候,缓存自己估一个时长。MDN 举例说,内容一年没更新,客户端会给出一个重用期,长度约为存放时间的十分之一[1]。这个估算落在哪一天没人说得准,改版之后的可见时间因此带上了随机性,所以每个响应都该显式指定标头。
验证要有比对的凭据,HTTP 里给了两种。Last-Modified 取文件修改时间,格式复杂难解析,多台服务器之间也不容易对齐,ETag 就是作为替代被标准化的[1]。ETag 的值由服务器自己定,常见做法是取正文的散列、时间戳的散列,或者直接用版本号[2]。
HTTP/1.1 200 OK
Content-Type: text/html
ETag: "33a64df5"
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: no-cache
客户端把存下来的值放进 If-None-Match 发回去,两边一致就收到 304 Not Modified,不一致就收到 200 OK 加新版正文[2]。比对还分强弱:强验证要求逐字节相同,弱验证只要求内容语义相同,页脚时间不一样在弱验证下算同一份[3]。弱验证的标记是值前面的 W/ 前缀[2]。这些指令和状态码的语义写在 RFC 9111 里[4]。
文件名带哈希
第三条路不改标头,改网址。缓存按 URL 区分响应,内容一变、网址跟着变,旧副本再也匹配不上[1]。四种写法如下。
bundle.v123.js
bundle.js?v=123
bundle.YsAIAAAA-QG4G6kCMAMBAAAAAAAoK.js
bundle.js?v=YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
前两种把版本号写进网址,后两种写的是内容哈希[1]。哈希串从文件正文算出来,正文改一个字符它就变。Google 给的例子是 style.x234dff.css,带指纹的网址可以放心配一年的新鲜期[5]。webpack 这类构建工具能在打包时自动分配这串指纹[5]。
主资源用不上这条路。HTML 自身的地址不能这么改,让用户去记带指纹的页面文件名不现实,Google 说这类地址只能回源确认[5]。MDN 给的配法是 no-cache,再加上 ETag 与 Last-Modified[1]。
三条路的代价
三条路的取舍各不相同,左边是省下的开销,右边是要付的成本。
| 做法 | 省下什么 | 付出什么 |
|---|---|---|
Cache-Control 定时 |
新鲜期内一个请求都不发 | 旧内容撑到过期为止 |
ETag 验证 |
正文没变时不再传正文 | 每次仍有一次往返 |
| 文件名带哈希 | 一年内零请求、零验证 | 引用要重写,构建多一步 |
时间控制的毛病是慢。改了版,旧副本要等 max-age 到期才作废,这期间用户看到的还是旧页,爬虫抓到的也是旧页。验证控制的毛病是省不掉往返,正文没变时只省掉传输那一段。ETag 的生成还有额外成本:值要从正文算出来,集群里每台机器算出的值还得一致,同一网址在两台机器上给出不同值,验证就失败[1]。哈希命名的毛病是杂,一次改动牵扯的不只一个文件,HTML 里的引用要同步更新,旧文件名在缓存和磁盘上都留着,站点文件数随版本累积。
改完还不生效的时候
按这个次序查,先确定问题在哪一层。
- 看网址变了没有。带了新哈希就是新资源,网址没变说明还在用旧副本。
- 分清旧内容存在哪一层。用户强刷时,浏览器发出的请求会带
Cache-Control: no-cache,本地副本被绕过[1],强刷之后仍是旧页,问题在节点或者源站。 - 清节点。HTTP 缓存规范没有定义删除缓存的方法,托管缓存可以用面板操作、接口调用或者重启实时删掉已经存下的响应[1]。
- 检查
immutable配在了哪些资源上。写了它,有效期内客户端不再发验证请求,用户手动刷新也不发[1],这类资源只能等过期,所以只能给带哈希的网址用。
附录
参见
参考资料
官方(境外)
- 《HTTP 缓存》,MDN Web 文档。
- 《ETag》,MDN Web 文档。
- 《HTTP 条件请求》,MDN Web 文档。
- 《RFC 9111 : STD 98 : HTTP Caching》,IETF,2022-06。
- 《使用 HTTP 缓存防止不必要的网络请求》,web.dev。
外部链接
无。