核心是确保CDN缓存的压缩版本与原始资源严格对应:统一压缩策略、禁用CDN侧重复压缩、启用gzip_static预生成压缩文件、固化缓存键排除Accept-Encoding干扰、添加ETag/X-Static-Hash等校验头。

核心在于让 CDN 节点缓存的压缩版本与原始资源严格对应,避免因 Accept-Encoding 差异、缓存键冲突或内容不一致导致 404、乱码或降级加载。关键不是“让 CDN 存压缩包”,而是确保 Nginx 和 CDN 对同一请求返回完全一致的响应体 + 响应头组合。
统一压缩策略并禁用 CDN 侧重复压缩
CDN 通常自带 Gzip 压缩开关(如 Cloudflare 的 “Auto Minify” 或阿里云 CDN 的 “智能压缩”),若开启,可能在 Nginx 已压缩基础上二次压缩,或对已压缩文件再尝试压缩,造成损坏。务必在 CDN 控制台中:
- 关闭所有自动压缩、自动 minify 功能
- 确认 CDN 仅作缓存与转发,不修改响应体或 Content-Encoding
- 检查回源请求头,确保 CDN 回源时携带 Accept-Encoding: gzip(否则 Nginx 不压缩)
使用 gzip_static 实现零歧义的静态压缩交付
比动态压缩更可靠:Nginx 不实时压缩,而是查找预生成的 .gz 文件(如 main.js → main.js.gz)。只要文件存在且权限正确,Nginx 就返回它,并自动设置 Content-Encoding: gzip 和正确的 Content-Length。这从源头消除了“同一 URI 有时返回压缩、有时不返回”的风险。
配置示例:
location ~* \.(js|css|svg|woff2|ttf)$ {
gzip_static on; # 启用静态压缩查找
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri.gz $uri =404;
}
注意:必须提前用 gzip 命令或构建工具生成 .gz 文件,并确保它们与原文件同目录、同权限、mtime 一致(部分 CDN 会校验 Last-Modified)。
固化缓存键(Cache Key),排除编码干扰
默认情况下,CDN 缓存键常包含 Accept-Encoding,导致 gzip / identity 版本被当作不同资源缓存——这虽合理,但易引发一致性维护负担。更稳妥做法是:在 CDN 回源配置中,强制抹除 Accept-Encoding 头,让 Nginx 统一按 gzip_static 或 gzip on 决策,然后由 Nginx 自行决定是否返回压缩体。
同时,在 Nginx 回源 location 中显式控制缓存键:
proxy_cache_key "$host$request_uri"; # 不含 $http_accept_encoding
这样 CDN 所有对 /a.js 的请求,无论浏览器是否支持 gzip,都回源取同一个缓存项;而 Nginx 内部通过 gzip_static 或 gzip on 确保该缓存项始终是压缩版(只要 .gz 存在)。
添加强校验头,便于监控与排查
在 Nginx 静态资源 location 中加入可验证的一致性标识:
-
add_header ETag ""$(md5sum $request_filename.gz | cut -d' ' -f1)"";(需配合 Lua 或外部脚本实现精准 ETag) - 更实用的是统一启用
gzip_vary on;,让 CDN 和浏览器知道该资源变体依赖 Accept-Encoding —— 若你已统一回源行为,此头可省略;若保留多变体,则必须开启,否则中间缓存可能混用 - 添加
add_header X-Static-Hash "$upstream_http_last_modified";,将文件修改时间透传,便于比对 CDN 缓存与源站文件新鲜度











