7.4.4 expires与cache-control缓存策略

expires 与 cache-control 是静态资源缓存优化的核心策略,目标是在保证更新可控的前提下延长浏览器与中间缓存的有效期,减少重复请求与带宽消耗。本节通过原理示意、可执行配置、验证命令、排错与练习给出完整操作路径。

原理草图(浏览器/代理/CDN 缓存决策)

文章图片

核心概念与区别(含命令解释)
- Expires:HTTP/1.0 绝对时间,受客户端时间影响;适合旧客户端兼容。
- Cache-Control:HTTP/1.1 指令集合,优先级高,常用指令:
- max-age=秒:强缓存时间
- no-cache:不使用强缓存,但允许协商缓存
- no-store:完全不缓存
- public/private:是否允许共享缓存
- immutable:资源不可变(搭配版本化文件)
- 优先级Cache-Control > Expires。建议两者同时配置,保证兼容性。

安装与基础准备(示例环境)

# 以 Ubuntu 为例安装 Nginx(其他发行版可替换为 yum/dnf)
sudo apt update
sudo apt install -y nginx

# 查看版本与编译参数(确认支持)
nginx -V

# 启动并查看状态
sudo systemctl enable --now nginx
sudo systemctl status nginx --no-pager

完整配置示例(包含路径、说明与预期效果)
文件路径:/etc/nginx/conf.d/static-cache.conf

server {
    listen 80;
    server_name static.example.com;
    root /var/www/html;

    # 1) 静态资源:长缓存 + immutable
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
        expires 30d;  # 设置 Expires 绝对时间
        add_header Cache-Control "public, max-age=2592000, immutable";
        # 预期效果:浏览器 30 天强缓存,不回源
    }

    # 2) HTML:禁用强缓存,启用协商缓存
    location ~* \.(html)$ {
        expires -1;
        add_header Cache-Control "no-cache";
        # 预期效果:每次都走协商缓存,变更及时可见
    }

    # 3) 敏感接口:禁止缓存
    location /api/ {
        add_header Cache-Control "no-store";
        # 预期效果:不在浏览器或代理中缓存
    }
}

配置生效与验证(命令与解释)

# 语法检查
sudo nginx -t

# 重新加载配置
sudo systemctl reload nginx

# 验证响应头(静态资源)
curl -I http://static.example.com/app.js
# 关键输出应包含:
# Cache-Control: public, max-age=2592000, immutable
# Expires: (未来时间)

# 验证 HTML 响应头
curl -I http://static.example.com/index.html
# 关键输出应包含:
# Cache-Control: no-cache

# 验证敏感接口
curl -I http://static.example.com/api/user
# 关键输出应包含:
# Cache-Control: no-store

协商缓存示例(ETag/Last-Modified 与 304)

# 第一次请求,记录 ETag 与 Last-Modified
curl -I http://static.example.com/index.html

# 使用 If-None-Match/If-Modified-Since 进行协商缓存
curl -I \
  -H 'If-None-Match: "etag_value_here"' \
  -H 'If-Modified-Since: Tue, 01 Aug 2023 12:00:00 GMT' \
  http://static.example.com/index.html
# 预期效果:若未变更返回 304

常见排错与定位(含命令解释)
- 问题1:Cache-Control 未生效
- 可能原因:配置文件未加载或被其他 location 覆盖
- 排查命令:
bash # 查看最终生效配置 sudo nginx -T | sed -n '1,200p' # 查找是否被更高优先级 location 覆盖 sudo nginx -T | grep -n "location .*js"
- 问题2:浏览器仍然回源
- 可能原因:资源未版本化或响应头缺失
- 排查命令:
bash curl -I http://static.example.com/app.js | egrep -i "cache-control|expires|etag|last-modified"
- 问题3:缓存时间异常(过短/过长)
- 可能原因:max-age 配置错误(秒数)或客户端时间不准
- 验证命令:
bash # 检查服务器时间与 NTP timedatectl

练习
1. 设计一套“图片资源 180 天强缓存 + HTML 协商缓存”的配置,并验证响应头。
2. 为 /api/ 增加 no-store 后,使用 curl -I 验证并记录效果。
3. 修改 max-age 为 10 秒,观察浏览器在 10 秒内的请求变化(可用开发者工具 Network 面板)。

最佳实践要点
- 静态资源使用文件名版本化(hash),搭配 max-age 长缓存与 immutable
- HTML 入口页面禁用强缓存,保证发布可见。
- 使用 ETag/Last-Modified 协同,减少重复下载。
- CDN 与浏览器缓存策略保持一致,避免边缘节点与客户端冲突。