Cache Components

2026年9月6日

Cache Components 是 Next 16 的可选能力:同一页里,构建期能确定的先做成静态壳,请求期才知道的放进 Suspense 洞里流式补上,需要的动态数据还可以显式缓存。用来缓和「全静态不能更新」和「全动态首屏慢」两边的别扭。

先在配置里打开:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  cacheComponents: true,
};

export default nextConfig;
ts

三种内容

类型何时算例子
静态构建 / 预渲染fs.readFileSync、静态 import、纯计算
动态每次请求fetch 实时接口、cookies()headers()
缓存动态算一次,按策略复用'use cache' + cacheLife

动态块必须包在 Suspense 里,外壳才能先出去。


静态块

import { readFileSync } from "node:fs";

export default function Page() {
  const json = JSON.parse(readFileSync("data.json", "utf8"));
  return <h1>{json.title}</h1>;
}
tsx

没有网络、没有用户上下文,构建时就能定稿。


动态块

import { Suspense } from "react";
import { cookies } from "next/headers";

async function Who() {
  const res = await fetch("https://api.example.com/name");
  const data = await res.json();
  const jar = await cookies();
  return (
    <p>
      {data.name} / cookie: {jar.get("token")?.value ?? "无"}
    </p>
  );
}

export default function Page() {
  return (
    <div>
      <h1>首页</h1>
      <Suspense fallback={<p>加载动态区…</p>}>
        <Who />
      </Suspense>
    </div>
  );
}
tsx

底层接近 PPR:先出带占位的静态 HTML,动态结果随后替换对应槽。开发者工具里能看到占位 id 和替换脚本,不必手写。


随机数、时间戳

Math.random()Date.now() 每次都不同。开启 Cache Components 后,如果在预渲染阶段同步调用,框架会报错,避免「随机值被冻住」。

await connection(),明确告诉框架:这段等真正有请求再跑。

import { connection } from "next/server";
import { Suspense } from "react";

async function Live() {
  await connection();
  return <p>{Math.random()}</p>;
}

export default function Page() {
  return (
    <Suspense fallback={<p></p>}>
      <Live />
    </Suspense>
  );
}
tsx

use cache 和 cacheLife

把动态结果缓存起来,并声明寿命:

import { cacheLife } from "next/cache";
import { Suspense } from "react";

async function CachedName() {
  "use cache";
  cacheLife("hours");
  const res = await fetch("https://api.example.com/name");
  return <p>{(await res.json()).name}</p>;
}

export default function Page() {
  return (
    <Suspense fallback={<p></p>}>
      <CachedName />
    </Suspense>
  );
}
tsx

cacheLife 可以传预设名,或自己写秒数:

预设大致用途
seconds行情、比分
minutes时间线
hours天气、库存
days博客正文
weeks更新很慢的栏目
max几乎不变的页

三个字段:stale(客户端先信多久)、revalidate(过后后台再生成)、expire(多久没人访问就彻底丢掉)。

下一篇把「没开 Cache Components」时的 revalidate / force-dynamic / cache: 'no-store' 也放在一起。


参考文档