Apache的Header指令支持强缓存控制,但需启用mod_headers模块;Cache-Control应按资源类型精准设置,如静态资源用public,max-age=31536000,immutable,HTML避免强缓存,并通过FilesMatch等限定作用域以防止误配。

Header指令在Apache中是否支持强缓存控制
支持,但前提是 mod_headers 模块已启用。很多默认安装的 Apache(尤其是 CentOS/RHEL 的包管理版本)会禁用该模块,直接写 Header set Cache-Control 会导致 500 错误且错误日志里出现 Invalid command 'Header'。先确认模块状态:
apachectl -M | grep headers,没输出就需启用:
a2enmod headers(Debian/Ubuntu)或在 httpd.conf 中取消 #LoadModule headers_module modules/mod_headers.so 的注释。
Cache-Control 值怎么设才真正生效
强缓存依赖客户端(浏览器)是否信任服务端响应头,而 Cache-Control 的值必须明确、无冲突。常见错误是混用 no-cache 或 max-age=0,这会让浏览器每次发条件请求,失去强缓存意义。正确做法是按资源类型区分:
- 静态资源(JS/CSS/图片):用
Cache-Control: public, max-age=31536000, immutable(1年 + immutable 表示内容不变,可跳过后续验证) - HTML 页面:避免强缓存,至少保留
Cache-Control: no-cache或用短周期如max-age=60 - 带版本号的文件(如
app.a1b2c3.js):可放心设长max-age,因为 URL 变了缓存自然失效
注意:immutable 在较老浏览器(如 IE、旧版 Safari)不支持,但不影响回退到 max-age 行为。
如何只对特定后缀文件设置 Header
全局设置 Header 容易误伤 HTML 或 API 接口,推荐用 <FilesMatch> 或 <LocationMatch> 精确作用域。例如只对静态资源加缓存头:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
<FilesMatch "\.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
关键点:
- 正则中
woff2?覆盖woff和woff2,问号要转义成woff2\?吗?不用 —— Apache 的FilesMatch使用的是基本正则(BRE),?不是元字符,直接写woff2?反而匹配不到woff2;应写成woff2?是错的,正确是woff(2)? - 如果用
<LocationMatch>,路径匹配基于 URL,不是磁盘路径,适合代理场景 - 配置写在
.htaccess中时,需确保AllowOverride FileInfo已开启,否则被忽略
为什么设置了 Header 却没看到响应头生效
最常被忽略的是 Apache 配置加载顺序和覆盖逻辑。以下情况会导致 Header 不出现:
- 多个
Header指令冲突:例如某处写了Header unset Cache-Control,后面又set,但未指定always—— 默认只对 2xx 响应生效,而unset可能已在更早阶段执行 - 反向代理下(如 Nginx 前置),Apache 的
Header可能被上游覆盖,此时需在代理层也配置,或改用Header always set - PHP 脚本通过
header()函数显式输出了Cache-Control,会覆盖 Apache 的设置(除非用Header always set)
调试建议:用 curl -I https://yoursite.com/test.js 直接看响应头,避开浏览器缓存干扰;再检查 Apache 错误日志是否有模块加载失败或语法错误。
强缓存真正起效的前提,是资源 URL 稳定性与缓存头严格匹配,而不是堆砌参数。一个没带哈希的 main.js 配 max-age=1年 只会让用户卡在旧版本里——这点比指令怎么写重要得多。


















