必须手动启用xampp中的mod_expires模块,否则所有expires指令均被忽略;需编辑httpd.conf取消#loadmodule expires_module modules/mod_expires.so注释,重启apache,并在中配置expiresactive on及具体规则。

确认 mod_expires 模块已启用
XAMPP 默认不启用 mod_expires,即使配置了规则也不会生效。必须手动开启模块加载,否则所有 ExpiresActive 和 ExpiresByType 都会被忽略。
打开 XAMPP\apache\conf\httpd.conf,搜索:LoadModule expires_module modules/mod_expires.so。如果该行被注释(开头有 #),删掉它;如果没有这行,就在其他 LoadModule 行附近手动添加。
- 改完后务必重启 Apache,否则模块不会加载
- 可通过访问
http://localhost/server-info(需启用mod_info)或运行httpd -M | findstr expires(Windows 命令行)验证是否在已启用模块列表中 - Linux/macOS 用户注意:XAMPP for macOS/Linux 的路径和模块名可能略有差异,但 Windows 版 XAMPP 统一用
mod_expires.so
在 httpd.conf 中添加有效的 Expires 规则
把缓存规则直接写进 httpd.conf 是最稳妥的做法——比放在 .htaccess 更高效,也避免因 AllowOverride 未开放导致失效。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
在 httpd.conf 文件末尾追加:
<ifmodule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 week"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
</ifmodule>
-
access表示从用户请求时刻起算,modification表示从文件最后修改时间起算;静态资源推荐用access,更可控 - 不要写成
EXpiresByType(大小写错误)或漏掉引号,Apache 会静默忽略整段<ifmodule></ifmodule> -
ExpiresDefault是兜底规则,但不能覆盖text/html等动态内容的语义——HTML 页面通常不该设长缓存,这里设 1 周是为防误配,实际建议保持默认或显式设为短时间(如"access plus 5 minutes")
验证 Expires 头是否真实发出
浏览器开发者工具的 Network 面板里看响应头,是最直接的验证方式。仅看 HTML 是否“加载快了”不可靠,因为可能只是本地磁盘读取或 DNS 缓存干扰。
- 选中一个 CSS 文件(如
style.css),查看 Headers → Response Headers,确认存在Expires和Cache-Control字段 - 若只有
Cache-Control: max-age=...而无Expires,说明mod_expires生效但时区/系统时间异常(Expires是绝对时间戳,依赖服务器时间准确) - 若两者都缺失,大概率是模块没启用、
ExpiresActive Off、或配置位置不在生效作用域内(比如错放到<directory></directory>外且未继承) - 注意:Chrome 有时会显示
from disk cache却不显示响应头——换 Firefox 或用curl -I http://localhost/style.css直接查原始响应头更可靠
CSS/JS 更新后用户仍看到旧版本怎么办
这是 Expires 缓存最典型的副作用:缓存太强,发布新版本后用户本地仍用旧文件,导致样式错乱或 JS 报错。
- 开发阶段建议把 CSS/JS 缓存设短,例如
"access plus 10 minutes",上线后再调长 - 生产环境推荐「文件名哈希」方案:构建时生成
main.a1b2c3.css,HTML 中引用带哈希的路径,这样每次更新文件名就自然绕过缓存 - 临时调试可用强制刷新(Ctrl+F5)或清空浏览器缓存,但不能作为发布流程的一部分
- 不要依赖
Cache-Control: no-cache或Pragma来“取消”已有缓存——它们只影响本次请求,对已缓存副本无效
mod_expires 配置本身很简单,真正容易出问题的是模块启用状态、配置作用域和缓存更新机制。尤其要注意 Windows 下 XAMPP 控制面板重启 Apache 后,有时服务进程未真正退出,旧配置仍在运行——遇到“改了不生效”,先任务管理器杀掉所有 httpd.exe 再重启。










