2024年5月23日星期四
Next.js 15 RC
发布者Next.js 15 发布候选版 (RC) 现已推出。此早期版本允许您在即将发布的稳定版本之前测试最新功能。
- React: 支持 React 19 RC、React 编译器(实验性)和水合错误改进
- 缓存:
fetch请求、GET路由处理器和客户端导航不再默认缓存 - 部分预渲染(实验性): 用于增量采用的新布局和页面配置选项
next/after(实验性): 新 API,用于在响应流结束后执行代码create-next-app: 更新了设计,并添加了一个新标志以在本地开发中启用 Turbopack- 捆绑外部包(稳定版): 适用于 App 和 Pages 路由的新配置选项
立即试用 Next.js 15 RC
npm install next@rc react@rc react-dom@rcReact 19 RC
Next.js App Router 构建于 React canary 频道之上,该频道允许开发者在 v19 发布之前使用这些新的 React API 并提供反馈。
Next.js 15 RC 现已支持 React 19 RC,其中包括客户端和服务器的新功能,例如 Actions。
阅读 Next.js 15 升级指南、React 19 升级指南,并观看 React Conf 主题演讲了解更多。
注意: 某些第三方库可能尚未与 React 19 兼容。
React 编译器(实验性)
React 编译器是由 Meta 的 React 团队创建的一种新的实验性编译器。该编译器通过理解纯 JavaScript 语义和 React 规则,深入理解您的代码,从而可以为您的代码添加自动优化。该编译器减少了开发者通过 useMemo 和 useCallback 等 API 进行手动记忆化的工作量——使代码更简单、更易于维护且不易出错。
通过 Next.js 15,我们增加了对 React 编译器的支持。
安装 babel-plugin-react-compiler
npm install babel-plugin-react-compiler然后,在 next.config.js 中添加 experimental.reactCompiler 选项
const nextConfig = {
experimental: {
reactCompiler: true,
},
};
module.exports = nextConfig;可选地,您可以将编译器配置为以“选择加入”模式运行,如下所示
const nextConfig = {
experimental: {
reactCompiler: {
compilationMode: 'annotation',
},
},
};
module.exports = nextConfig;注意: React 编译器目前只能通过 Babel 插件在 Next.js 中使用,这可能会导致构建时间变慢。
了解更多关于 React 编译器和可用的 Next.js 配置选项。
水合错误改进
Next.js 14.1 改进了错误消息和水合错误。Next.js 15 继续在此基础上进行改进,增加了改进的水合错误视图。水合错误现在会显示错误的源代码,并提供解决问题的建议。
例如,这是 Next.js 14.1 中以前的水合错误消息

Next.js 15 RC 已将其改进为

缓存更新
Next.js App Router 推出了有主见的缓存默认设置。这些设置旨在默认提供最高性能的选项,并可在需要时选择退出。
根据您的反馈,我们重新评估了我们的缓存启发式及其与部分预渲染 (PPR) 等项目以及使用 fetch 的第三方库的交互方式。
在 Next.js 15 中,我们将 fetch 请求、GET 路由处理器和客户端路由缓存的缓存默认设置从默认缓存更改为默认不缓存。如果您希望保留以前的行为,您可以继续选择缓存。
我们将在未来几个月继续改进 Next.js 中的缓存,并将在 Next.js 15 GA 公告中分享更多详细信息。
fetch 请求不再默认缓存
Next.js 使用 Web fetch API 缓存选项来配置服务器端 fetch 请求如何与框架的持久 HTTP 缓存交互。
fetch('https://...', { cache: 'force-cache' | 'no-store' });no-store- 每次请求都从远程服务器获取资源,不更新缓存。force-cache- 从缓存(如果存在)或远程服务器获取资源并更新缓存。
在 Next.js 14 中,如果未提供 cache 选项,则默认使用 force-cache,除非使用了动态函数或动态配置选项。
在 Next.js 15 中,如果未提供 cache 选项,则默认使用 no-store。这意味着 fetch 请求将不再默认缓存。
您仍然可以通过以下方式选择缓存 fetch 请求:
- 在单个
fetch调用中将cache选项设置为force-cache - 将单个路由的
dynamic路由配置选项设置为'force-static' - 将
fetchCache路由配置选项设置为'default-cache',以覆盖布局或页面中的所有fetch请求,使其使用force-cache,除非它们明确指定自己的cache选项。
GET 路由处理器不再默认缓存
在 Next 14 中,使用 GET HTTP 方法的路由处理器默认被缓存,除非它们使用了动态函数或动态配置选项。在 Next.js 15 中,GET 函数不再默认缓存。
您仍然可以使用静态路由配置选项(例如 export dynamic = 'force-static')选择缓存。
特殊的路由处理器,如 sitemap.ts、opengraph-image.tsx和 icon.tsx,以及其他 元数据文件,除非它们使用动态函数或动态配置选项,否则默认保持静态。
客户端路由缓存不再默认缓存页面组件
在 Next.js 14.2.0 中,我们引入了一个实验性的 staleTimes 标志,允许自定义配置 路由缓存。
在 Next.js 15 中,此标志仍然可访问,但我们将默认行为更改为页面段的 staleTime 为 0。这意味着当您在应用程序中导航时,客户端将始终反映导航中激活的页面组件的最新数据。然而,仍有一些重要的行为保持不变:
- 共享布局数据不会从服务器重新获取,以继续支持部分渲染。
- 前进/后退导航仍将从缓存中恢复,以确保浏览器可以恢复滚动位置。
- Loading.js 将保持缓存 5 分钟(或
staleTimes.static配置的值)。
您可以通过设置以下配置选择恢复以前的客户端路由缓存行为:
const nextConfig = {
experimental: {
staleTimes: {
dynamic: 30,
},
},
};
module.exports = nextConfig;部分预渲染的增量采用(实验性)
在 Next.js 14 中,我们引入了部分预渲染 (PPR)——一种将静态渲染和动态渲染结合在同一页面上的优化。
Next.js 目前默认使用静态渲染,除非您使用 动态函数(例如 cookies()、headers() 和未缓存的数据请求)。这些 API 会将整个路由选择到动态渲染。使用 PPR,您可以将任何动态 UI 包装在 Suspense 边界中。当新的请求传入时,Next.js 将立即提供静态 HTML 外壳,然后在同一个 HTTP 请求中渲染并流式传输动态部分。
为了允许增量采用,我们添加了一个 experimental_ppr 路由配置选项,用于将特定的布局和页面选择到 PPR。
import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
export const experimental_ppr = true
export default function Page() {
return {
<>
<StaticComponent />
<Suspense fallback={...}>
<DynamicComponent />
</Suspense>
</>
};
}要使用此新选项,您需要在 next.config.js 文件中将 experimental.ppr 配置设置为 'incremental'。
const nextConfig = {
experimental: {
ppr: 'incremental',
},
};
module.exports = nextConfig;一旦所有段都启用了 PPR,就可以安全地将 ppr 值设置为 true,并为整个应用程序和所有未来的路由启用它。
我们将在 Next.js 15 GA 博客文章中分享更多关于 PPR 路线图的信息。
了解更多关于 部分预渲染。
使用 next/after 在响应后执行代码(实验性)
在处理用户请求时,服务器通常会执行与计算响应直接相关的任务。但是,您可能需要执行诸如日志记录、分析和其他外部系统同步等任务。
由于这些任务与响应没有直接关系,因此用户不应等待它们完成。在响应用户之后推迟工作带来了一个挑战,因为无服务器函数在响应关闭后会立即停止计算。
after() 是一个新的实验性 API,它通过允许您安排在响应流完成后处理的工作来解决此问题,从而使辅助任务能够在不阻塞主要响应的情况下运行。
要使用它,请将 experimental.after 添加到 next.config.js
const nextConfig = {
experimental: {
after: true,
},
};
module.exports = nextConfig;然后,在服务器组件、服务器操作、路由处理器或中间件中导入该函数。
import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
export default function Layout({ children }) {
// Secondary task
after(() => {
log();
});
// Primary task
return <>{children}</>;
}了解更多关于 next/after。
create-next-app 更新
对于 Next.js 15,我们更新了 create-next-app 的设计。

运行 create-next-app 时,会有一个新提示询问您是否要为本地开发启用 Turbopack(默认为 否)。
✔ Would you like to use Turbopack for next dev? … No / Yes可以使用 --turbo 标志启用 Turbopack。
npx create-next-app@rc --turbo为了更轻松地开始一个新项目,CLI 中添加了一个新的 --empty 标志。这将删除任何多余的文件和样式,从而生成一个最小的“hello world”页面。
npx create-next-app@rc --empty优化外部包捆绑(稳定版)
捆绑外部包可以改善应用程序的冷启动性能。在 App Router 中,外部包默认捆绑,您可以使用新的 serverExternalPackages 配置选项选择退出特定的包。
在 Pages Router 中,外部包默认不捆绑,但您可以使用现有的 transpilePackages 选项提供要捆绑的包列表。使用此配置选项,您需要指定每个包。
为了统一 App 和 Pages Router 之间的配置,我们引入了一个新选项 bundlePagesRouterDependencies,以匹配 App Router 的默认自动捆绑。然后,如果需要,您可以使用 serverExternalPackages 选择退出特定的包。
const nextConfig = {
// Automatically bundle external packages in the Pages Router:
bundlePagesRouterDependencies: true,
// Opt specific packages out of bundling for both App and Pages Router:
serverExternalPackages: ['package-name'],
};
module.exports = nextConfig;了解更多关于 优化外部包。
其他更改
- [重大更改] 最低 React 版本现为 19 RC
- [重大更改] next/image: 移除
squoosh,转而使用sharp作为可选依赖项 (PR) - [重大更改] next/image: 默认
Content-Disposition更改为attachment(PR) - [重大更改] next/image: 当
src具有前导或尾随空格时报错 (PR) - [重大更改] Middleware: 应用
react-server条件以限制不推荐的 react API 导入 (PR) - [重大更改] next/font: 移除对外部
@next/font包的支持 (PR) - [重大更改] next/font: 移除
font-family散列 (PR) - [重大更改] 缓存:
force-dynamic现在将为 fetch 缓存设置no-store默认值 (PR) - [重大更改] Config: 默认启用
swcMinify(PR)、missingSuspenseWithCSRBailout(PR) 和outputFileTracing(PR) 行为并移除已弃用的选项。 - [重大更改] 移除 Speed Insights 的自动检测(现在必须使用专用的 @vercel/speed-insights 包)(PR)
- [重大更改] 移除动态站点地图路由的
.xml扩展名,并统一开发和生产环境中的站点地图 URL (PR) - [改进] 元数据: 更新了在 Vercel 上托管时
metadataBase的环境变量回退 (PR) - [改进] 修复
optimizePackageImports混合命名空间和命名导入时的树摇晃 (PR) - [改进] 并行路由: 为不匹配的 catch-all 路由提供所有已知参数 (PR)
- [改进] Config
bundlePagesExternals现已稳定并重命名为bundlePagesRouterDependencies - [改进] Config
serverComponentsExternalPackages现已稳定并重命名为serverExternalPackages - [改进] create-next-app: 新项目默认忽略所有
.env文件 (PR) - [文档] 改进了身份验证文档 (PR)
- [文档]
@next/env包 (PR)
要了解更多信息,请查阅 升级指南。
贡献者
Next.js 是由 3000 多名独立开发者、Google 和 Meta 等行业合作伙伴以及 Vercel 核心团队共同努力的成果。本次发布由以下人员贡献:
- Next.js 团队:Andrew、Balazs、Ethan、Janka、Jiachi、Jimmy、JJ、Josh、Sam、Sebastian、Sebbie、Shu、Steven、Tim、Wyatt 和 Zack。
- Turbopack 团队:Alex、Benjamin、Donny、Leah、Maia、OJ、Tobias 和 Will。
- Next.js 文档:Delba、Steph、Michael、Anthony 和 Lee。
非常感谢 @devjiwonchoi, @ijjk, @Ethan-Arrowood, @sokra, @kenji-webdev, @wbinnssmith, @huozhi, @domdomegg, @samcx, @Jaaneek, @evanwinter, @wyattjoh, @kdy1, @balazsorban44, @feedthejim, @ztanner, @ForsakenHarmony, @kwonoj, @delbaoliveira, @stipsan, @leerob, @shuding, @xiaohanyu, @timneutkens, @dvoytenko, @bobaaaaa, @bgw, @gaspar09, @souporserious, @unflxw, @kiner-tang, @Ehren12, @EffectDoplera, @IAmKushagraSharma, @Auxdible, @sean-rallycry, @Jeffrey-Zutt, @eps1lon, @jeanmax1me, @unstubbable, @NilsJacobsen, @PaulAsjes, @adiguno, @ryan-nauman, @zsh77, @KagamiChan, @steveluscher, @MehfoozurRehman, @vkryachko, @chentsulin, @samijaber, @begalinsaf, @FluxCapacitor2, @lukahartwig, @brianshano, @pavelglac, @styfle, @symant233, @HristovCodes, @karlhorky, @jonluca, @jonathan-ingram, @mknichel, @sopranopillow, @Gomah, @imddc, @notrab, @gabrielrolfsen, @remorses, @AbhiShake1, @agadzik, @ryota-murakami, @rishabhpoddar, @rezamauliadi, @IncognitoTGT, @webtinax, @BunsDev, @nisabmohd, @z0n, @bennettdams, @joeshub, @n1ckoates, @srkirkland, @RiskyMH, @coopbri, @okoyecharles, @diogocapela, @dnhn, @typeofweb, @davidsa03, @imranolas, @lubieowoce, @maxhaomh, @mirasayon, @blvdmitry, @hwangstar156, @lforst, @emmerich, @christian-bromann, @Lsnsh, @datner, @hiro0218, @flybayer, @ianmacartney, @ypessoa, @ryohidaka, @icyJoseph, @Arinji2, @lovell, @nsams, @Nayeem-XTREME, @JamBalaya56562, @Arindam200, @gaojude, @qqww08, @todor0v, @coltonehrman, 和 @wiesson 提供的帮助!


