文章目录
-
- 每日一句正能量
- 前言
- 一、三级缓存架构:从边缘到浏览器的层层拦截
- [二、HTTP 缓存头:精细化到资源类型的策略](#二、HTTP 缓存头:精细化到资源类型的策略)
- [三、Service Worker:离线可用与智能拦截](#三、Service Worker:离线可用与智能拦截)
- 四、ISR:增量静态再生的工程实践
- 五、缓存失效:版本控制与清理策略
- [六、完整配置:Next.js 缓存优化集成](#六、完整配置:Next.js 缓存优化集成)
- 结语

每日一句正能量
"真正的高贵,不是优于别人,而是优于过去的自己。"
与他人比较("优于别人")是焦虑和迷失的永恒源头,因为它依赖于不可控的外部变量。而与过去的自己比较,则是将人生变为一场可以自我度量、自我掌控的进化游戏。"优于"不一定是功成名就,可以是更平和、更懂得爱、更快速地从挫折中恢复
前言
2026 年 3 月,Codex 官网在一次产品发布活动中经历了流量洪峰------单日 UV 从平日的 8 万飙升至 120 万。令人意外的是,源站服务器的 CPU 使用率始终维持在 15% 以下,数据库连接池从未触达上限,页面平均加载时间反而从 1.2 秒降至 0.4 秒。这一反直觉的表现并非偶然,而是三级缓存架构的系统性胜利:CDN 边缘缓存拦截了 92% 的请求,Service Worker 为回访用户提供了毫秒级响应,浏览器 HTTP 缓存则消除了重复资源的网络往返。本文将完整拆解这套缓存体系的设计原理、配置细节与失效策略。
一、三级缓存架构:从边缘到浏览器的层层拦截
现代 Web 应用的缓存不是单点决策,而是一个分层协作系统。Codex 官网的三级缓存按"距离用户由远及近"排列:
CDN 边缘缓存 是第一道防线,部署在全球 100 余个节点上。当用户请求 /docs/getting-started 时,最近的边缘节点会检查本地缓存。如果命中,直接返回预渲染的 HTML,无需回源。Vercel Edge Network 的实测数据显示,全球 95% 的用户可以在 50ms 内获得边缘缓存响应。
Service Worker 缓存是第二道防线,运行在用户浏览器内部。它拦截所有网络请求,对预缓存的静态资源(JS、CSS、字体)直接返回本地副本,对 API 请求根据策略决定走缓存还是网络。对于回访用户,Service Worker 可以在完全离线的状态下渲染应用壳(App Shell)。
浏览器 HTTP 缓存 是最后一道防线,由 Cache-Control 等响应头控制。它不需要任何 JavaScript 代码,是浏览器原生实现的最高效缓存层。对于哈希化的静态资源(如 main.a3f2b1c.js),浏览器会在一年内直接读取本地磁盘缓存,甚至不发送条件请求验证。

二、HTTP 缓存头:精细化到资源类型的策略
"设置一个长的 max-age"是最常见的缓存误区。不同资源的更新频率、可变性和重要性截然不同,需要差异化的缓存策略。
对于哈希化静态资源(构建时注入内容哈希的文件名),Codex 官网配置:
Cache-Control: public, max-age=31536000, immutable
immutable 指令来自 RFC 8246,它明确告知浏览器:这个 URL 对应的资源永远不会改变。即使用户按下强制刷新(Ctrl+F5),浏览器也不会发送 If-None-Match 条件请求------因为它知道服务器端的资源内容与本地缓存完全一致。这一优化将静态资源的重复请求彻底归零。
对于HTML 页面,策略则完全不同。Codex 的文档页使用 ISR(增量静态再生),配置为:
Cache-Control: public, max-age=60, stale-while-revalidate=86400
这行指令的含义是:页面在首次生成后缓存 60 秒,60 秒内所有请求直接返回缓存副本;60 秒后,缓存进入"陈旧但可用"状态,边缘节点仍然立即返回缓存副本,但同时在后台向源站发起重新验证请求;如果源站生成了新版本,下一次请求将获得更新后的内容。用户在整个过程中始终体验到亚秒级响应,而内容的"新鲜度"误差被控制在 60 秒以内。

三、Service Worker:离线可用与智能拦截
Service Worker 是浏览器与网络之间的可编程代理。Codex 官网使用 Workbox 8.x(Google Chrome Aurora 团队维护)自动生成和管理 Service Worker,避免手写 fetch 事件的繁琐与易错。
预缓存策略 在 Service Worker 安装阶段自动完成。构建工具(Next.js / Vite)会生成一份带内容哈希的资源清单(__WB_MANIFEST),Workbox 在 install 事件中批量下载这些资源存入 CacheStorage。这意味着用户在首次访问时,除了当前页面所需的资源,Service Worker 还在后台静默缓存了应用壳和其他关键路由的依赖------为后续导航的瞬时加载打下基础。
ts
// sw.ts
import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
// 自动预缓存构建产物(由构建工具注入清单)
precacheAndRoute(self.__WB_MANIFEST);
// 图片资源:CacheFirst,缓存 30 天
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 30 * 24 * 60 * 60,
}),
],
})
);
// API 请求:NetworkFirst,10 秒超时后回退缓存
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({
cacheName: 'api-cache',
networkTimeoutSeconds: 10,
plugins: [
new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 5 * 60,
}),
],
})
);
// 文档内容:StaleWhileRevalidate,即时响应 + 后台刷新
registerRoute(
({ url }) => url.pathname.startsWith('/docs/'),
new StaleWhileRevalidate({
cacheName: 'docs-content',
plugins: [
new ExpirationPlugin({
maxEntries: 200,
maxAgeSeconds: 24 * 60 * 60,
}),
],
})
);
离线兜底是 Service Worker 的另一项核心能力。当用户处于完全离线状态时,对未缓存的路由请求会返回预置的离线页面:
ts
import { setCatchHandler } from 'workbox-routing';
setCatchHandler(async ({ request }) => {
// 对导航请求返回离线页面
if (request.destination === 'document') {
return caches.match('/offline.html');
}
return Response.error();
});

四、ISR:增量静态再生的工程实践
Next.js 的 ISR(Incremental Static Regeneration)是连接 CDN 缓存与源站渲染的桥梁。它解决了静态站点生成(SSG)的核心矛盾:构建时预渲染保证了速度,但内容更新需要重新构建整个站点;服务端渲染(SSR)保证了实时性,但每个请求都消耗服务器资源。
ISR 的折中方案是"首次请求时渲染并缓存,后续请求返回缓存,后台定期重新验证"。Codex 官网的文档页配置如下:
tsx
// app/docs/[slug]/page.tsx
export const revalidate = 60; // 60 秒后后台重新验证
export async function generateStaticParams() {
// 构建时预渲染热门页面
const slugs = await getPopularDocSlugs();
return slugs.map((slug) => ({ slug }));
}
export default async function DocPage({ params }: { params: { slug: string } }) {
const doc = await fetchDoc(params.slug);
return <DocContent doc={doc} />;
}
generateStaticParams 在构建时生成热门文档的静态页面,确保首访用户也能获得 CDN 缓存响应。对于长尾文档(如冷门 API 参考页),首次请求会触发服务端渲染,结果存入 CDN 缓存,后续访问即享受静态性能。
revalidate = 60 是 Codex 在"新鲜度"与"服务器负载"之间的平衡选择。对于文档内容,60 秒的延迟是可接受的;对于博客文章,这个值放宽到 600 秒;对于定价页等极少变化的内容,则使用 86400 秒(24 小时)。
2026 年的 Next.js 16 还引入了 on-demand revalidation (按需重新验证),允许在 CMS 内容更新时主动触发缓存失效,而非被动等待 revalidate 超时:
ts
// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
export async function POST(request: Request) {
const { path, secret } = await request.json();
if (secret !== process.env.REVALIDATE_SECRET) {
return Response.json({ error: 'Invalid secret' }, { status: 401 });
}
revalidatePath(path);
return Response.json({ revalidated: true });
}

五、缓存失效:版本控制与清理策略
缓存的最大敌人不是未命中,而是"陈旧命中"------用户看到了过期的内容却毫不知情。Codex 官网通过三层机制确保缓存可控可失效:
文件名哈希 是静态资源缓存的基石。Next.js 在构建时为每个 JS/CSS 文件注入内容哈希(如 main.a3f2b1c.js),文件内容变化即哈希变化,URL 随之变化。旧版本的缓存自然失效,因为没有任何页面再引用旧的 URL。这是唯一一种"零成本、零风险"的缓存失效方式。
Service Worker 版本管理 通过 skipWaiting() 和 clients.claim() 实现即时更新。当新版本部署时,新的 Service Worker 进入 waiting 状态,旧版本继续服务当前页面。Codex 在应用壳中监听 waiting 事件,提示用户刷新以获取更新:
ts
// 客户端注册逻辑
const wb = new Workbox('/service-worker.js');
wb.addEventListener('waiting', () => {
// 显示"新版本可用,点击刷新"提示
showUpdateNotification(() => {
wb.messageSkipWaiting();
wb.addEventListener('controlling', () => window.location.reload());
});
});
wb.register();
CDN 缓存标签 用于按需批量失效。Codex 为每个文档页面附加缓存标签(如 doc:react-hooks、category:frontend),当某类内容批量更新时,通过 API 调用一次性清除所有匹配标签的缓存,而非逐个 URL 清除。
六、完整配置:Next.js 缓存优化集成
以下是 Codex 官网的 next.config.ts 缓存相关配置,整合了 HTTP 头、ISR 与静态资源策略:
ts
// next.config.ts
import type { NextConfig } from 'next';
const config: NextConfig = {
// ISR 全局默认(可被页面级覆盖)
experimental: {
staleTimes: {
dynamic: 30,
static: 300,
},
},
// 自定义 HTTP 响应头
headers: async () => [
{
source: '/_next/static/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
{
source: '/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=60, stale-while-revalidate=86400',
},
],
},
],
// 图片优化缓存
images: {
minimumCacheTTL: 60 * 60 * 24 * 30, // 30 天
formats: ['image/avif', 'image/webp'],
},
};
export default config;
结语
缓存策略的设计本质是"在数据新鲜度与系统性能之间寻找最优平衡"。Codex 官网的三级缓存架构证明,当 CDN 边缘缓存、Service Worker 本地缓存和浏览器 HTTP 缓存协同工作时,系统可以在承受 15 倍流量洪峰的同时保持亚秒级响应。关键不在于设置最长的 max-age,而在于为每种资源类型匹配最合适的策略:哈希资源用 immutable,动态页面用 stale-while-revalidate,API 响应用 NetworkFirst,离线场景用 CacheFirst。在下一篇文章中,我们将探讨前端监控体系------从性能埋点到错误追踪的完整可观测性方案。
转载自:https://blog.csdn.net/sghtgjfhv/article/details/164166926
欢迎 👍点赞✍评论⭐收藏,欢迎指正