直接答案:对 25 个装备企业官网各取第一个 CSS 与第一个外链 JS,共 50 个资源请求:43 个返回 200、2 个 404、1 个不可达、4 个未声明。43 个 200 资源里,23 个有正 max-age(可缓存)、18 个没有 Cache-Control、2 个 max-age=0。可缓存的 23 个中,12 个用 14 天、4 个 12 小时、3 个一年;中位 14 天。
“没有 Cache-Control”不等于“完全不缓存”:浏览器可能启发式缓存,但不可控;本次 43 个 200 里,CSS 有 20 个、JS 有 19 个仍带 Last-Modified,CSS 13 个、JS 11 个带 ETag,可以作为验证器,但不能替代显式缓存策略。
方法:首个 CSS/JS,HEAD 优先,GET 兜底
复用第 4 期 25 个首页缓存,解析每站第一个声明的样式表与第一个外链脚本(内联不计)。2026-11-07 22:41 逐条请求一次,优先 HEAD,带 Accept-Encoding: gzip, br 与 Referer;HEAD 返回 400/403/405/501 或连接失败时改用 GET。记录状态、方法、Cache-Control、ETag、Last-Modified、Vary、Content-Encoding、Content-Type、长度、Age、Server 与 CDN 标记。
缓存策略按 Cache-Control 分类:可缓存 = max-age > 0;no-store / private / no-cache = 私有不缓存;max-age=0 单列;没有该头 = missing。没有请求浏览器,也不验证 CDN 边缘是否命中。
| 项 | CSS | JS |
|---|---|---|
| 请求 | 25 | 25 |
| 200 | 21 | 22 |
| 404 | 1 | 1 |
| 不可达 | 0 | 1 |
| 未声明 | 3 | 1 |
| 200 中可缓存 | 12 | 11 |
| 200 中无 Cache-Control | 9 | 9 |
| 200 中 max-age=0 | 0 | 2 |
结果:18/43 没有显式缓存策略
| 页 | CSS 策略 / max-age | JS 策略 / max-age |
|---|---|---|
| E01 | missing / — | max-age=0 |
| E02 | cacheable / 12h | cacheable / 12h |
| E03 | cacheable / 14d | cacheable / 14d |
| E04 | cacheable / 1y | cacheable / 1y |
| E06 | cacheable / 14d | cacheable / 14d |
| E08 | missing / — | missing / — |
| E09 | cacheable / 14d | cacheable / 14d |
| E11 | cacheable / 12h | 不可达 |
| E12 | cacheable / 12h | max-age=0 |
| E13 | missing / — | missing / — |
| E14 | cacheable / 14d | cacheable / 14d |
| E16 | missing / — | missing / — |
| E17 | missing / — | missing / — |
| E18 | 未声明 | 未声明 |
| E19 | missing / — | missing / — |
| E20 | 未声明 | missing / — |
| E22 | cacheable / 14d | cacheable / 14d |
| E23 | cacheable / 14d | cacheable / 14d |
| E24 | private / 404 | private / 404 |
| E25 | 未声明 | cacheable / 1y |
| E26 | missing / — | missing / — |
| E27 | missing / — | missing / — |
| E28 | cacheable / 1h | cacheable / 30d |
| E29 | cacheable / 5m | cacheable / 5m |
| E30 | missing / — | missing / — |
23 个可缓存资源的 max-age 分布:14 天 12 个、12 小时 4 个、一年 3 个、5 分钟 2 个、1 小时 1 个、30 天 1 个;中位 14 天。E01 与 E12 的 JS 是 max-age=0,每次使用都要重新验证;E24 的两个 404 仍带 private/no-cache,说明错误响应也有一套缓存策略。
三个容易误判的点
- 没有 Cache-Control 不等于没有缓存。 浏览器可能启发式缓存;但策略不可控。18/43 属于这种情况,不能写成“全部不缓存”。
- ETag / Last-Modified 不是显式 max-age。 43 个 200 里 39 个有 Last-Modified、24 个有 ETag,但验证器只解决“是否变了”,不决定“多久不用问”。
- HEAD 与 GET 要分开记。 E13 的 CSS、E19 的 JS 在 HEAD 下分别 502/连接失败,用 GET 才拿到 200;E11 的外链 JS 两次都不可达。不记录方法会把工具失败当成服务器策略。
对验收的启示
- CSS/JS 要显式写 Cache-Control。 至少区分 HTML 与带指纹的静态资源;本次 18/43 没有该头。
- 版本化 URL 再配长缓存。 一年 max-age 只适合文件名带 hash 的资源;E04 两个资源都是一年。
- max-age=0 要确认是否必要。 E01/E12 的 JS 每次都要验证;如果文件没变,会增加往返。
- 错误响应也要有策略。 E24 的 404 带 private/no-cache;不要把 404 当成可缓存的静态资源。
- 把验证器与 max-age 分开记。 ETag/Last-Modified 不能替代 Cache-Control,验收表要两列。
局限
- 25 站 pilot:同一批首页缓存;不是行业总体,也不代表全部 134 CSS / 204 JS。
- 每类只取首个资源:不代表长尾;未测带指纹的构建产物、CDN 边缘命中或浏览器实际缓存。
- HEAD 优先:3 个资源用 GET 兜底,1 个仍不可达;方法已逐行记录,不把失败当策略。
- 单次快照:2026-11-07 22:41;未复测改版或不同地区。
- 只读响应头:不判断内容是否正确、是否阻塞渲染或 TTFB。
数据与复算
匿名数据:equipment-homepage-css-js-cache-headers-2026.csv(50 行 × 20 列:类型、是否找到、站外、状态、方法、Cache-Control、策略、max-age、ETag、Last-Modified、Vary、编码、Content-Type、长度、Age、Server、CDN、错误、时间)。仓库内为 docs/research/2026-11-homepage-css-js-cache-headers.csv。
采集:Python urllib,HEAD 优先、GET 兜底,带 Accept-Encoding: gzip, br 与 Referer;策略分类复用 scripts/cache_compression_probe.py 的 evaluate()。站点与完整 URL 不公开。
配套:首页静态资源清单 pilot、首页 HTML 压缩 pilot、首页缓存与压缩 pilot。
数据来源与口径
- 样本:第 4 期 25 个首页缓存(2026-10-31);每站首个声明 CSS 与首个外链 JS。
- 请求:2026-11-07 22:41,HEAD 优先、GET 兜底,25 站 × 2 类,共 50 次。
- 分类:max-age > 0 可缓存;no-store/private/no-cache 私有不缓存;max-age=0 单列;无头 missing。
常见问题
没有 Cache-Control 就没有缓存吗?
不一定。浏览器可能做启发式缓存,但策略不可控;本文只记录响应头,不测浏览器实际缓存。
为什么 404 也列 private/no-cache?
E24 的 CSS/JS 返回 404,但响应仍带 private/no-cache;它不是可用静态资源,错误响应也需要明确策略。
max-age=0 是什么意思?
每次使用前都要重新验证;E01 与 E12 的 JS 是这种情况,验证本身可能增加往返。
ETag / Last-Modified 能替代 Cache-Control 吗?
不能。验证器解决“资源变没变”,max-age 解决“多久不用问”;本文 43 个 200 里 39 个有 Last-Modified、24 个有 ETag。
为什么 HEAD 和 GET 结果不同?
E13 的 CSS、E19 的 JS 在 HEAD 下 502/失败,GET 才 200;E11 的外链 JS 两次都不可达。方法逐行记录,不把工具失败当服务器策略。
数据能复核吗?
可以。50 行 × 20 列匿名 CSV 在仓库内;采集时间、方法、状态、Cache-Control、max-age、ETag、Last-Modified、Vary、编码、长度与错误都逐条记录;站点与完整 URL 不公开。
相关:首页首图缓存头 pilot。