Next.js 16.4
TL;DR · AI 摘要
Next.js 16.4引入Cache Components编程模型,成为Next.js 17默认方案,实现更灵活的缓存控制与性能优化。
核心要点
- Cache Components将于Next.js 17成为默认编程模型
- 使用'use cache'指令可实现组件级缓存控制
- 新项目默认启用Cache Components,旧项目提供迁移工具
结构提纲
按章节快速跳转。
介绍Next.js 16.4核心改进方向及技术背景
解释Cache Components作为新型缓存控制方案的核心机制
通过'use cache'指令实现组件级缓存生命周期管理
提供next upgrade --agent命令辅助旧项目迁移
包含内存占用降低、构建速度提升等多维度优化
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- Next.js 16.4新特性
- Cache Components
- 组件级缓存控制
- 声明式缓存生命周期管理
- 替代旧版App Router缓存机制
- 迁移工具
- next upgrade --agent命令
- 版本特定迁移指导
- 性能优化
- 开发环境内存占用降低
- 构建时间缩短
- 生产包体积优化
金句 / Highlights
值得收藏与分享的关键句。
Cache Components通过'use cache'实现组件级缓存控制,类似HTTP Cache-Control头
Next.js 16.4后新项目默认启用Cache Components,旧项目提供迁移工具链
该版本包含React 19.3支持,生产环境包体积进一步缩减
Next.js 16.4 | Next.js
返回博客
2026年10月6日,星期二
Next.js 16.4
发布者
9+
Next.js 团队
15
成员
在 16.x 系列发布中,我们引入了一种新的编程模型,解决了您从一开始就对 App Router 的诸多困扰:
- 即使是个性化页面,也能实现快速的初始加载
- 为服务端渲染应用提供即时的客户端导航
- 使缓存功能可选、声明式且可组合
这种新编程模型称为 Cache Components,将在 Next.js 17 中成为默认选项。
在此发布之前,我们并未普遍推荐它,因为存在一些场景无法达到旧模型在成本和性能方面的保证。
本次发布包含关键特性,填补了这些空白。
从 Next.js 16.4 开始,我们很高兴推荐 Cache Components 作为所有 Next.js 应用的最佳选择。
从今天起,通过 create-next-app 创建的所有新应用将默认启用 Cache Components。新项目可以无保留地享受新模型的所有优势。
对于现有应用,我们正在投入更多资源开发更智能的工具,帮助代码库迁移至新模型。新的 next upgrade --agent 命令会为代理提供特定版本的升级指导,而专门的 Skills 功能将协助代理完成任何必要的重构以采用 Cache Components。
Next.js 16.4 还为所有 Next.js 应用带来了多项开箱即用的改进,包括开发环境内存使用和磁盘占用减少、编译时间缩短、生产环境包体积更小,以及支持 React 19.3。
以下是本次发布的主要内容概述,从 Cache Components 开始:
什么是 Cache Components?
Cache Components 是一组功能,允许您标记组件树中的特定部分以进行缓存。可以将 'use cache' 看作是组件级别的 Cache-Control HTTP 头:
import { cacheLife } from 'next/cache';
export default async function DashboardPage() {
const currentUser = await getCurrentUser();
return (
<div>
<p>Welcome, {currentUser.name}</p>
<Suspense fallback={<Loading />}>
<Projects userId={currentUser.id} />
</Suspense>
</div>
);
}
async function Projects({ userId }) {
'use cache';
cacheLife('hours');
const projects = await db.query.projects.findMany({
where: eq(projectsTable.userId, userId),
});
return (
<div>
{projects.map((project) => (
<p key={project.id}>{project.name}</p>
))}
</div>
);
}Next.js 在渲染页面时会解释这些 'use cache' 注解,在浏览器中缓存组件的 UI(在客户端导航期间),并根据需要在服务器上缓存(在服务端渲染期间或构建时提前生成)。
这些可组合的注解允许您在单个页面中混合使用客户端缓存、完全可插拔的服务端缓存和请求时渲染,同时取代了旧版 App Router 的隐式缓存行为。
要了解更多关于 Cache Components 的信息,请阅读缓存指南。
Cache Components 新特性
在本文中,我们使用 "Cache Components" 指代新的编程模型,您现在可以通过在 Next.js 配置中启用两个标志来使用它:
next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
cacheComponents: true,
partialPrefetching: true,
};
export default nextConfig;缓存组件(Cache Components)最初发布时没有包含部分预取(Partial Prefetching)功能,但现在该功能已被视为模型的一部分。你可以从我们之前的发布文章中了解更多关于部分预取的信息。
接下来是 16.4 版本中缓存组件的新特性。
确保外壳、预取或页面为静态内容
“use cache” 的一个显著特性是能够构建页面,使服务器在单个响应中同时流式传输静态和动态内容。
例如,你可以将当前用户的头像与一个静态预渲染的博客文章组合在一起:
export
default
function
Page
() {
return
(
<>
<
UserAvatar
/>
<
Content
/>
</>
);
}
// 此组件在请求时渲染
async
function
UserAvatar
() {
const
currentUser
=
await
getCurrentUser
();
// ...
}
// 此组件为静态预渲染
async
function
Content
() {
'use cache'
;
await
fetch
(
'...'
);
// ...
}Next 可以从缓存中提供预渲染的博客文章(例如你的应用的 /public 文件夹或 CDN),并在同一个 HTTP 响应中在请求时渲染 UserAvatar。
这种灵活性使你能够构建具有复杂 UI 的应用,而不会牺牲速度或动态性。但在某些情况下,你可能希望构建完全静态的页面。在这些情况下,一个动态组件可能会降低原本优化良好的网站的性能或成本特性。
在 Next.js 16.4 中,ensureStatic 提供了一种简单的方法,可确保路由的外壳、预取或完整导航为静态内容。对于希望避免无意计算并降低服务器成本的应用,这使你能够防止动态组件意外地进入某个路由。
例如,如果我们希望强制上述示例中的博客文章页面始终为静态,并且添加像 UserAvatar 这样的动态组件永远不可能,我们可以向路由中添加 export const ensureStatic:
export
const
ensureStatic
=
'navigation'
;
export
default
function
Page
() {
return
(
<>
<
UserAvatar
/> {
/* 🔴 此组件会导致构建失败 */
}
<
Content
/>
</>
);
}通过将 ensureStatic 设置为 "navigation",如果此页面中包含任何动态内容,Next 将导致构建失败,从而确保导航到此路由时永远不会在请求时渲染。
虽然 "navigation" 是最严格的选项,但如果你需要更精细的控制,也可以将 ensureStatic 设置为 "prefetch"(确保指向此路由的显式预取链接仅获取静态内容)或 "shell"(确保首次发现此路由时仅获取静态内容)。
除了在单个页面上使用外,你还可以将 ensureStatic 添加到布局中,以将相同的保证应用于该布局内的所有页面。例如,你可以将 ensureStatic = 'navigation' 添加到根布局中,以轻松确保网站中所有页面的导航都是静态的:
// app/layout.tsx
export
const
ensureStatic
=
'navigation'
;
export
default
async
function
RootLayout
({ children }) {
// ...
}然后,如果某些页面开始需要动态内容,你可以将此设置下推到嵌套布局中。
许多动态应用可能不需要此功能,但对于优化后的网站(如电商商店、营销页面或博客),ensureStatic 是一种简单的方法,可防止不需要的请求时渲染。
了解更多关于保持页面静态和 ensureStatic 配置的信息。
从预取中排除内容
预取是提升 Next.js 应用程序用户体验的强大方式。
通过使用 <Link prefetch> 或 useRouter().prefetch(),你可以在实际导航发生之前预先渲染页面的缓存 UI,从而消除加载状态。
例如,让我们来看一个简单的电子邮件应用。这是一个显示每条消息链接的收件箱:
async
function
Inbox
() {
const
messages
=
await
db
.
query
.
messages
.findMany
();
return
(
<
nav
>
{
messages
.map
((message)
=>
(
<
Link
href
=
{
`/message/
${
message
.id
}
`
}
key
=
{
message
.id}
>
{
message
.subject}
</
Link
>
))}
</
nav
>
);
}这是消息页面,首次加载消息线程时会显示一个旋转器,之后会在浏览器中缓存以便后续访问:
// app/message/[id]/page.jsx
export
default
function
Page
({ params }) {
return
(
<
Suspense
fallback
=
{<
Spinner
/>}>
{
params
.then
(({ id })
=>
(
<
Message
id
=
{id} />
))}
</
Suspense
>
);
}
async
function
Message
({ id }) {
const
[
message
,
thread
]
=
await
Promise
.all
([
getMessage
(id)
,
getThread
(id)
]);
return
(
<>
<
p
>{
message
.subject}</
p
>
<
div
>{
message
.body}</
div
>
{
thread
.map
((message)
=>
(
<
div
key
=
{
message
.id}>{
message
.body}</
div
>
))}
</>
);
}
async
function
getMessage
(id) {
'use cache'
;
return
db
.
query
.
messages
.findFirst
({ where
:
eq
(
messages
.id
,
id) });
}
async
function
getThread
(id) {
'use cache'
;
return
db
.
query
.
messages
.findMany
({
where
:
eq
(
messages
.threadId
,
id)
,
orderBy
:
asc
(
messages
.createdAt)
,
});
}虽然这可以让用户立即查看已加载的消息,但首次打开消息时仍会看到加载旋转器。
为了消除这个初始加载状态,我们可以为收件箱的链接添加预取功能:
async
function
Inbox
() {
const
messages
=
await
db
.
query
.
messages
.findMany
();
return
(
<
nav
>
{
messages
.map
((message)
=>
(
<
Link
prefetch
href
=
{
`/message/
${
message
.id
}
`
}
key
=
{
message
.id}
>
{
message
.subject}
</
Link
>
))}
</
nav
>
);
}现在,每个链接会在可见时立即预取消息页面上所有缓存的数据和 UI,这样用户点击时即可立即显示。
这通过消除应用中的加载状态提供了出色的用户体验,但也意味着每个可见链接都会提前加载整个消息线程,即使用户从未打开这些消息。对于我们的电子邮件应用来说,这可能会消耗过多资源或给服务器带来过大压力。
与其简单地关闭预取功能,更好的解决方案是只预取第一条消息,并将其余消息线程的渲染推迟到用户实际导航时再进行。
在 Next.js 16.4 中,我们可以实现这一点。新的导航 API 允许你在预取期间排除加载缓存内容,从而有效地将这些内容推迟到实际导航时再加载。
在我们的示例中,我们可以将线程提取到一个新组件中,并添加 await navigation() 以将其从预取中排除:
import
{ navigation }
from
'next/cache'
;
async
function
Message
({ id }) {
const
message
=
await
getMessage
(id);
return
(
<>
<
p
>{
message
.subject}</
p
>
<
div
>{
message
.body}</
div
>
<
Suspense
fallback
=
{<
Spinner
/>}>
<
Thread
id
=
{id} />
</
Suspense
>
</>
);
}
async
function
Thread
({ id }) {
await
navigation
();
const
thread
=
await
getThread
(id);
return
(
<>
{
thread
.map
((message)
=>
(
<
div
key
=
{
message
.id}>{
message
.body}</
div
>
))}
</>
);
}现在,Message 页面在预取期间仅渲染第一条消息,并等待完整的导航加载线程的其余部分,再从数据库中渲染。
除了 navigation() 之外,我们还新增了 prefetch() ,你可以通过 await 来调用,以排除原本会被包含在路由外壳中的缓存内容。这样,渲染这些内容将被推迟到使用 <Link prefetch> 或 useRouter().prefetch() 的显式预取时进行。
这些 API 让你能够更精细地控制不同导航阶段加载的数据,从而以适合你应用的方式在主动渲染和延迟渲染之间取得平衡。
了解如何将工作推迟到后续阶段,以及查看导航和预取 API 的参考文档。
新增代理功能
我们正在投入开发代理工具,使 Next.js 成为一个持续帮助你保持应用安全和更新的系统。Next.js 16.4 在文档、Skills 和验证工具的基础上,通过代理升级和反馈功能,帮助我们从你的开发实践中学习,并将改进带回你的应用。
代理升级
新的 next upgrade 命令新增了 --agent 参数,可帮助代理从头到尾完成应用的升级。它会检查你安装的版本,选择目标发布版本,并为代理准备迁移指南、所需的代码转换工具和验证步骤。代理会应用更新,解决迁移问题,并验证应用是否仍能正常运行。
你或你的代理可以从应用目录中运行:
Terminal
npx
next@canary
upgrade
--agent=latest使用 next@canary 可运行最新的升级工具,即使你的应用使用的是旧版 Next.js。你的代理将获得最新指导,帮助你的应用升级到最新版本。
保持最新是第一步。为了帮助你持续跟进,Next.js 16.4 引入了实验性功能 experimental.agentUpgrade 。当你或你的代理运行 next dev 或 next build 时,Next.js 会自动提示你或你的代理有相关升级可用,无需你手动检查。当你选择升级时,它会以你配置的策略启动相同的代理工作流。
你可以在 Next.js 配置中设置这些提醒:
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
experimental
:
{
agentUpgrade
:
'security'
,
}
,
};
export
default
nextConfig;- 'security'(默认策略):提醒你关于修复已知漏洞的升级,这些漏洞会影响你安装的版本。
- 'latest':提醒你关于更新的主要或次要版本发布,并使用最新的升级策略保持应用的最新状态。
- false:禁用升级提醒。
我们还在为这个标志设计未来的策略,以帮助代理以惯用方式采用新功能和编程模型变更,例如迁移到缓存组件。目前,你可以使用我们的 Skills 来采用缓存组件和部分预取功能,让代理帮助你迁移到新模型。
了解更多关于使用代码代理升级和 agentUpgrade 配置的信息。
代理反馈
在构建和升级应用时,代码代理经常会遇到框架错误、文档不清晰或需要变通方法的情况。新的实验性代理反馈工作流允许它们准备草稿报告,你可以审阅并选择将其发送给 Next.js 团队。
当使用推荐的 create-next-app 设置创建新应用时,代理反馈默认是启用的。对于现有应用,你可以通过 Next.js 配置启用此功能:
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
experimental
:
{
agentFeedback
:
true
,
}
,
};
export
default
nextConfig;启用此功能后,next dev 会为你的代理添加指令,使其在运行时收集潜在问题。任务完成后,代理会生成报告草稿并在你的浏览器中打开供你审阅。
代理被指示忽略源代码、日志、密钥和项目特定的细节。你可以编辑或丢弃每份报告,直到你选择“发送反馈”前,不会发送任何内容。
代理反馈需要启用 Next.js Telemetry,且不会在 CI 环境中运行。
了解更多关于代理反馈和 agentFeedback 配置的信息。
所有应用的改进
更小的磁盘缓存大小
在 16.4 版本中,Turbopack 的磁盘缓存占用空间减少了 20-25%,无需任何配置更改。
现在缓存使用 Zstandard 压缩处理占用空间最多的数据,同时保留 LZ4 压缩用于元数据以保持快速缓存查找。我们还改进了压缩流程,更高效地清除过期数据。
懒加载服务器 HMR
此前,修改共享的服务器模块可能会触发对之前访问过的页面的更新,即使你不再查看这些页面。
在 16.4 版本中,Turbopack 仅在需要时编译并应用服务器更新。你正在查看的页面在编辑时仍会更新,而其他路由会等到再次请求时才更新。这减少了在浏览应用时的不必要的后台工作。
Turbopack 共享运行时
现在 Turbopack 将其运行时打包为一个跨路由共享的单个块。这减少了下载体积并提高了缓存命中率。
阅读我们的关于代码块的博客,了解此功能和其他代码块功能的更多信息。
更小的生产包体积
在 16.4 版本中,Turbopack 在生产环境中生成更短的 CSS Module 类名,从而减少样式表的大小以及引用它们的 HTML 和 JavaScript 的体积。开发环境仍保留较长的类名以便于调试。
此外,Turbopack 现在使用导出名称混淆来进一步减少包体积,通过缩短用于连接模块的内部 JavaScript 导出名称。
React 19.3
Next.js 16.4 集成 React 19.3,带来稳定的视图过渡和片段引用、新的 browser() API 等功能。
阅读 React 19.3 官方公告以全面了解新特性。
新增实验性功能
Rust React 编译器
React 编译器会自动优化组件渲染,减少手动记忆化的需求。其实验性的 Rust 版本自 16.3 版本引入以来,直接在 Next.js 中运行,而非通过 Babel。
在 16.4 版本中,新增的快速检查功能使其可以跳过不需要优化的文件。它还会在构建用于服务器渲染的客户端组件时避免重复优化,减少编译应用所需的工作量。
16.4 版本还包含多项编译器更新,提升了性能和正确性。Turbopack 团队贡献了内存分配改进,使 React 编译器的内存使用量减少了 30%,编译时间减少了 15%。
在 Next.js 配置中启用 React 编译器并选择 Rust 版本:
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
reactCompiler
:
true
,
experimental
:
{
turbopackRustReactCompiler
:
true
,
}
,
};
export
default
nextConfig;了解更多关于 Rust React 编译器和编译器性能改进的信息。
磁盘缓存清理
在您编辑应用程序时,Next.js 可能会保留不再需要的缓存编译工作。
在 16.4 版本中,一个实验性垃圾回收器会从内存和磁盘缓存中移除这些未使用的工作,有助于减少长时间开发会话中的资源占用。它还可以回收之前会话中的过期数据,例如已删除路由的缓存工作。
在 Next.js 配置中启用垃圾回收:
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
experimental
:
{
turbopackGc
:
true
,
}
,
};
export
default
nextConfig;了解更多关于 turbopackGc 的信息。
懒加载动态导入
动态导入允许您延迟加载代码,但 Next.js 通常在开发过程中提前编译这些代码。
在 16.4 版本中,您可以选择仅在浏览器请求时编译客户端动态导入。这减少了对尚未使用代码的初始编译工作,例如通过 import() 在按钮点击后加载的库。
在 Next.js 配置中启用懒加载动态导入:
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
experimental
:
{
turbopackLazyDynamicImports
:
true
,
}
,
};
export
default
nextConfig;部分 next/dynamic 导入仍然会被提前编译。
了解更多关于 turbopackLazyDynamicImports 的信息。
Worker 线程
Turbopack 在独立的 Node.js 进程中运行 Babel、PostCSS 和 webpack 加载器,这些进程通过套接字与 Turbopack 通信。
使用 Worker 线程后,这些工具会在单个进程中运行。这避免了独立进程和套接字通信的开销,旨在减少开发和构建过程中的内存和 CPU 使用率。
在 Next.js 配置中启用 Worker 线程:
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
experimental
:
{
turbopackPluginRuntimeStrategy
:
'workerThreads'
,
}
,
};
export
default
nextConfig;在 Node.js 24.13.1 及更新版本中,由于 Node.js 的一个 bug,Next.js 目前会回退到子进程。
了解更多关于 turbopackPluginRuntimeStrategy 的信息。
额外根目录和全局虚拟存储支持
Next.js 16.4 允许您声明额外根目录,从而可以跟踪项目根目录之外的符号链接依赖项。这使得在不扩展项目根目录以包含不相关目录的情况下,更容易处理链接的本地包。
这还启用了与 pnpm、Bun、Nub 和 aube 等工具的全局虚拟存储的集成,这些工具通过在项目和工作树之间共享已安装的依赖项来加速安装。自动集成计划在未来的版本中推出。
将包含链接依赖项的目录添加到 Next.js 配置中:
import
path
from
'node:path'
;
import
type
{ NextConfig }
from
'next'
;
const
nextConfig
:
NextConfig
=
{
experimental
:
{
turbopackAdditionalRoots
:
{
linkedPackages
:
{ path
:
path
.join
(__dirname
,
'../packages'
) }
,
}
,
}
,
};
export
default
nextConfig;对于 pnpm 的全局虚拟存储,请将 pnpm store path 报告的存储目录作为额外根目录添加。
了解更多关于额外根目录的信息。
Turbopack Bundle Analyzer
此版本为 Turbopack Bundle Analyzer 添加了重要功能。现在它:
- 在新的路由摘要首页中突出显示最大的客户端路由。
- 提供新的表格视图,可快速按路由资源的最大贡献者进行排序。
- 自动创建随时间运行的分析快照,并在应用程序更改时可以对比打包结果。
- 区分关键渲染路径上的模块,并在探索时允许您过滤掉异步依赖项。
捆绑包分析器现在还包含一个实验性的 next-bundle-optimizer 代理技能,可自动发现、诊断并优化您的应用所传输的 JavaScript 及其他资源数量。
使用该技能的步骤如下:
- 将您的 Next.js 应用升级到 16.4 版本。
- 运行命令
npx skills add vercel/next.js --skill next-bundle-optimizer。 - 在您选择的 AI 代理中运行
/next-bundle-optimizer。
了解更多关于 Turbopack Bundle Analyzer 的信息。
反馈与社区
我们希望您对尝试 Next.js 16.4 感到兴奋!
让您的代理通过我们的新 CLI 命令升级您的应用:
或自行升级:
npm
install
next@latest并通过以下渠道分享您的反馈,共同塑造 Next.js 的未来:
- GitHub Discussions
- GitHub Issues
- Discord 社区
贡献者
Next.js 是数千名开发者的共同努力成果。本次发布由以下团队带来:
- Next.js 团队:Andrew、Aurora、Dan、Hendrik、Janka、Jiwon、Joseph、Josh、Jude、Pete、Sam、Sebbie、Tim 和 Zack。
- Turbopack 团队:Andrew、Benjamin、Jimmy、Luke、Niklas、Tobias 和 Will。
衷心感谢 @kassens、@jamiboym、@6iu8a、@swarnava、@lukahartwig、@uaoa、@orzazade、@Samiislam851、@jarrensj、@sampoder、@martinfrancois、@leejpsd、@alangenfeld、@aryabyte21、@kostyniuk、@Stanzilla、@bmorros94、@ranger-ross、@styfle、@itsybitsci、@Amusac、@anujbolewar、@spirosikmd、@mezotv、@Xanaado、@marcoshernanz、@mlekhi、@dacgray、@molebox、@jgruica、@zeeshan56656、@lazerg、@hamidrezahanafi、@marceloboeira、@DavidIlie、@fireairforce、@QingHeSite、@niketchandivade、@biubiukam、@seanbeirnes、@0ldh、@fabian-hiller、@hardfist、@bryan-ferry、@gdborton、@hammadxcm、@syedsohailhussain1、@kelvinampofo、@koenpunt、@mayur9210、@Jashnavi25、@akselipalmer、@m-kawafuji、@Janpot 和 @kyamaz99 的帮助!