mod_expires未启用会导致ExpiresActive失效;ExpiresByType按MIME类型生效,ExpiresDefault为兜底规则;“access”基于请求时间,“modification”基于文件修改时间;Cache-Control优先级高于Expires,需统一配置并验证响应头。

mod_expires 模块没启用会导致 ExpiresActive 不生效
Apache 默认不启用 mod_expires,直接写配置会静默失败。先确认模块已加载:
apachectl -M | grep expires
如果没输出,需在配置中启用(Debian/Ubuntu 通常执行 a2enmod expires;CentOS/RHEL 则需在 httpd.conf 或 mods-enabled 中取消 LoadModule expires_module 行的注释)。
ExpiresByType 和 ExpiresDefault 的作用范围差异
ExpiresByType 只对匹配 MIME 类型的响应生效(如 text/css、image/jpeg),而 ExpiresDefault 是兜底规则,对所有未被 ExpiresByType 覆盖的资源起作用。常见误用是只设了 ExpiresDefault 却期望 CSS/JS 也走该规则——其实它们往往被 text/css 等更具体的类型覆盖了,得单独配。
示例配置片段:
<ifmodule mod_expires.c><br> ExpiresActive On<br> ExpiresByType text/css "access plus 1 year"<br> ExpiresByType application/javascript "access plus 1 year"<br> ExpiresByType image/jpg "access plus 2 weeks"<br> ExpiresDefault "access plus 1 day"<br></ifmodule>
“access” vs “modification” 时间基准容易混淆
access 表示用户首次请求该资源的时间点,之后按固定时长计算过期;modification 则以文件最后修改时间为准。静态资源(如打包后的 app.abc123.js)适合用 access,因为内容不变但文件名已带哈希;而未加版本号的 style.css 若用 access,用户可能长期看不到更新——此时应改用 modification 并确保 Web 服务器能正确读取文件 mtime。
注意:modification 对通过 PHP 或代理生成的内容无效,因为这类响应没有真实文件修改时间。
缓存头冲突:Cache-Control 优先级高于 Expires
现代浏览器以 Cache-Control: max-age= 为准,Expires 是 HTTP/1.0 兼容字段。mod_expires 默认只发 Expires,若你同时用了 Header set Cache-Control,两者不一致时浏览器会按 Cache-Control 执行。建议统一用 mod_headers 补充 Cache-Control:
Header set Cache-Control "max-age=31536000, public"
放在同一 块里,避免规则分散难维护。
实际生效前务必用 curl -I 或浏览器 DevTools 的 Network 面板验证响应头,尤其注意 304 是否正常返回——很多问题出在 ETag 或 Last-Modified 配置缺失,导致即使 Expires 正确,浏览器仍发条件请求却得不到 304。










