配置 CDN 以缓存 JavaScript (JS) 和 CSS 文件是前端性能优化的核心环节。这件事的本质,是通过全球分布的节点服务器,让用户从物理距离最近的地方加载这些静态资源,从而显著降低延迟、提高网站速度和可用性。
我将从基本原理出发,为你提供一个完整的配置思路、具体步骤和最佳实践。
核心原理:两层缓存与更新机制
要理解 CDN 配置,首先要明白缓存发生在两个层面:
-
源站 (Origin) -> CDN 边缘节点 (Edge Server):当一个地区的首位用户请求某个 JS/CSS 文件时,CDN 边缘节点会回到你的服务器(源站)获取文件,并根据你设定的规则将文件存储在自己的缓存中。之后该地区的其他用户请求同一个文件,CDN 会直接返回缓存副本,不再访问你的源站。
-
CDN 边缘节点 -> 用户浏览器 (Browser Cache):CDN 将文件发送给用户浏览器时,会附带 HTTP 头信息,告诉浏览器可以将这个文件在用户本地缓存多久。
配置的关键在于控制这两层缓存的有效期,以及在文件内容更新后,如何让用户和 CDN 都获取到最新的版本。
配置步骤详解
绝大多数 CDN 服务商(如 AWS CloudFront, Cloudflare, Akamai, 腾讯云 CDN, 阿里云 CDN 等)的配置流程都遵循以下逻辑。
第 1 步:选择并设置 CDN 服务
首先,你需要一个 CDN 服务商。在控制台中,通常需要创建一个“分发”或“加速域名”。
-
加速域名 (CDN Domain):你需要提供一个用于访问 CDN 资源的域名,例如
cdn.yourdomain.com。 -
源站信息 (Origin Server):你需要告诉 CDN 去哪里获取你的文件。这通常是你自己服务器的 IP 地址或域名,例如
origin.yourdomain.com。
配置完成后,CDN 服务商会给你一个 CNAME 记录,例如 xyz.cdn-provider.net。你需要到你的 DNS 服务商那里,将 cdn.yourdomain.com 的 CNAME 记录指向 xyz.cdn-provider.net。
第 2 步:配置缓存规则(核心)
这是最关键的一步,直接决定了 JS 和 CSS 的缓存效果。在 CDN 控制台的“缓存配置”或类似板块,你需要设定规则。
理想的缓存策略是:将文件名本身作为版本标识,然后设置一个“永久”缓存时间。
具体做法是:
-
设置一个超长的缓存时间 (TTL - Time To Live):
-
节点缓存过期时间:在 CDN 的配置中,找到针对 JS 和 CSS 文件类型的缓存规则(通常可以按文件后缀
.js,.css或目录来匹配)。 -
将其缓存时间设置为尽可能长,比如
31536000秒(1年)。 -
浏览器缓存过期时间:同样,CDN 会有“回源 HTTP 头”或“浏览器缓存过期时间”的设置。也将其设置为 1 年。
-
-
让 CDN 遵循源站的缓存头 (Cache-Control):
这是一个更专业、更灵活的方案。CDN 不自己决定缓存多久,而是完全听从你源站服务器返回的 HTTP Cache-Control 头部信息。
-
在 CDN 配置中,选择“继承源站”或“遵循源站的 Cache-Control”。
-
然后,在你的源站服务器(如 Nginx, Apache)上,为 JS 和 CSS 文件配置
Cache-Control响应头。
Nginx 配置示例:
Nginx
location ~* \.(css|js)$ { # 对所有匹配 .css 和 .js 的文件 # 设置 Cache-Control 头 # public: 表示任何缓存(包括CDN和浏览器)都可以缓存 # max-age: 缓存有效期,单位秒。31536000 = 1年 # immutable: (可选,但推荐) 告诉现代浏览器,这个文件内容绝对不会改变,不要为了检查更新而重新发起请求 add_header Cache-Control "public, max-age=31536000, immutable"; # 同样需要配置 CORS,允许跨域访问 add_header 'Access-Control-Allow-Origin' '*' always; }为什么设置为 1 年这么久? 因为我们不打算通过“等待缓存过期”来更新文件。我们将通过下面的“缓存刷新”机制来强制更新。
-
第 3 步:实现缓存刷新(Cache Busting)
如果你修改了 style.css 文件,但文件名不变,那么 CDN 和用户的浏览器都会因为长达一年的缓存而继续使用旧版本。这是最常见的问题。
解决方案是:文件内容改变时,文件名也必须改变。这被称为“缓存刷新”或“缓存破坏”(Cache Busting)。
最佳实践:文件名哈希 (File Hashing)
这是目前业界公认最好的方案。利用现代前端构建工具(如 Vite, Webpack, Parcel),在每次打包时,根据文件内容生成一个唯一的哈ッシュ值,并将其嵌入文件名中。
-
原始文件名:
main.js -
打包后文件名:
main.a1b2c3d4.js
当你的代码有任何改动,哪怕只是一个分号,生成的文件哈希值就会改变,得到一个全新的文件名(例如 main.e5f6g7h8.js)。
因为这是一个全新的 URL,所以 CDN 和浏览器都会将其视为一个新文件,从而主动去源站获取,自然就避免了缓存问题。
如何实现:
几乎所有的现代前端框架和构建工具都内置了此功能,通常在生产环境构建时自动启用。
-
Vite:
npx vite build默认就会生成带哈希值的文件。 -
Webpack: 通过配置
output.filename为[name].[contenthash].js来实现。
第 4 步:在 HTML 中引用 CDN 资源
最后一步,你需要修改你网站的 HTML 代码,将原来指向本地资源的 src 和 href 路径,替换为指向你的 CDN 域名。
修改前:
HTML
<link rel="stylesheet" href="/assets/css/style.css">
<script src="/assets/js/app.js"></script>
修改后(结合了文件名哈希):
HTML
<link rel="stylesheet" href="https://cdn.yourdomain.com/assets/css/style.a1b2c3d4.css">
<script src="https://cdn.yourdomain.com/assets/js/app.b5c6d7e8.js"></script>
这个替换过程也应该由你的构建工具或后端模板引擎自动完成。
其他关键配置与最佳实践
-
压缩 (Gzip / Brotli):确保在 CDN 设置中开启 Gzip 或 Brotli 压缩。这能将 JS/CSS 文件体积减小约 70%-80%。优秀的 CDN 会自动处理,但最好检查一下该功能是否开启。
-
HTTP/2 或 HTTP/3:确保你的 CDN 服务支持并开启了 HTTP/2 或 HTTP/3。这些新协议通过多路复用等技术,可以更高效地并行加载多个 JS/CSS 文件。
-
跨域资源共享 (CORS):由于你的资源(如
cdn.yourdomain.com)与你的主站(www.yourdomain.com)不在同一个域下,浏览器会实行同源策略。对于字体文件或通过 JS 发起的某些请求,必须在源站配置Access-Control-Allow-Origin头,允许来自 CDN 域名的访问(如上 Nginx 示例所示)。 -
预热 (Pre-warming):如果你预计有大的流量到来(例如产品发布),可以使用 CDN 提供的“预热”功能,主动将指定的 JS/CSS 文件推送到全球的边缘节点,这样即便是全球各地的第一个用户也能享受到缓存加速。
方案对比与最终建议
虽然有多种配置方式,例如通过查询字符串 (style.css?v=1.1) 来做缓存刷新,但我不推荐这种方式。一些旧的代理服务器或 CDN 节点可能会忽略查询字符串而只缓存 style.css 本身,导致更新失败。
最终建议的最佳方案组合:
-
CDN 选择:
-
对于大多数项目和个人开发者:Cloudflare 是最好的选择。它的免费套餐非常慷慨,包含了 CDN、DDoS 防护、免费 SSL 等,并且配置极其简单,通常是“一键式”的,因为它通过作为你整个网站的反向代理来工作,自动缓存静态资源。
-
对于需要高度定制化、与云服务(如 AWS S3)深度集成的项目:AWS CloudFront 是更强大和灵活的选择,但配置也相对复杂。
-
-
配置策略:
-
缓存刷新机制:必须使用文件名哈希。让构建工具(Vite/Webpack)在生产构建时自动生成如
app.a1b2c3d4.js的文件名。 -
缓存时间 (TTL):在源站服务器(Nginx/Apache)或 CDN 控制台,为
*.js和*.css文件设置一个长达一年的Cache-Control: public, max-age=31536000, immutable响应头。 -
辅助功能:确保开启 Gzip/Brotli 压缩和 HTTP/2 或 HTTP/3。
-
CORS:在源站为静态资源正确配置
Access-Control-Allow-Origin。
-
遵循这套方案,你可以构建一个极其高效且稳健的静态资源分发系统:文件一旦发布便可永久缓存,而任何更新都会因为文件名的改变而即时生效,完美平衡了缓存效率和更新的即时性。