2024 年 10 月 15 日,星期二
Next.js 15 RC 2
发布者继五月份发布首个 Next.js 15 Release Candidate 公告 之后,我们一直在根据您的反馈准备第二个 Release Candidate。以下是我们一直在努力的方向
@next/codemod upgrade
:轻松升级到最新的 Next.js 和 React 版本。- Turbopack 用于开发:性能改进和 Next.js 15 稳定性目标。
- 异步请求 API(破坏性更改):朝着简化的渲染和缓存模型迈出的渐进式一步。
- 服务器 Actions:通过不可猜测的端点和删除未使用的操作来增强安全性。
- 静态指示器:新的可视化指示器在开发期间显示静态路由。
next/form
:使用客户端导航增强 HTML 表单。next.config.ts
:对 Next.js 配置文件的 TypeScript 支持。instrumentation.js
(稳定版):用于服务器生命周期可观测性的新 API。- 开发和构建改进:改进的构建时间和更快的快速刷新。
- 自托管:更好地控制
Cache-Control
标头。 - Linting:增加了对 ESLint 9 的支持。
立即试用 Next.js 15 Release Candidate (RC2)
# Use the new automated upgrade CLI
npx @next/codemod@canary upgrade rc
# ...or upgrade manually
npm install next@rc react@rc react-dom@rc
注意: 此 Release Candidate 包含来自之前的 RC的所有更改。
使用 codemod CLI 实现平滑升级
我们在每个主要的 Next.js 版本中都包含 codemod(自动化代码转换),以帮助自动化升级破坏性更改。
为了使升级更加顺畅,我们发布了增强的 codemod CLI
npx @next/codemod@canary upgrade rc
此工具可帮助您将代码库升级到最新的稳定版或预发布版本。 CLI 将更新您的依赖项,显示可用的 codemod,并指导您完成应用它们的过程。命令行上指定的 dist 标签(@rc
、@canary
等)确定要升级到的版本。
了解有关 Next.js codemod 的更多信息。
用于开发的 Turbopack
用于本地开发的 Turbopack 将在 Next.js 15 的正式版本中变为稳定版,同时保持可选状态。您今天可以通过运行以下命令尝试它
next dev --turbo
感谢成千上万的开发人员参与了整个 Turbopack beta 和 Release Candidate 阶段的测试、问题报告和修复验证,自第一个 Next.js 15 Release Candidate 以来,我们已经解决了 54 个 GitHub 问题。除了社区的努力之外,我们在 vercel.com、v0.dev 和 nextjs.org 上的内部测试也帮助发现了许多额外的改进。
在过去的三个月中,我们专注于优化冷编译性能。与之前的版本相比,我们已经看到:
- 内存使用量减少 25–35%。
- 对于包含数千个模块的大型页面,编译速度提高 30–50%。
我们将在未来的版本中继续优化这些领域。
展望未来,Turbopack 团队在持久缓存、减少内存使用量以及用于 next build
的 Turbopack 方面取得了重大进展——96% 的测试通过。
注意: 查看 Turbopack 的所有受支持和不受支持的功能。
异步请求 API(破坏性更改)
在传统的服务器端渲染中,服务器在渲染任何内容之前都会等待请求。但是,并非所有组件都依赖于特定于请求的数据,因此没有必要等待请求来渲染它们。理想情况下,服务器会在请求到达之前尽可能多地准备。为了实现这一点,并为未来的优化奠定基础,我们需要知道何时等待请求。
因此,我们将依赖于特定于请求的数据(例如 headers
、cookies
、params
和 searchParams
)的 API 过渡为异步。
import { cookies } from 'next/headers';
export async function AdminPanel() {
const cookieStore = await cookies();
const token = cookieStore.get('token');
// ...
}
这是一个破坏性更改,会影响以下 API:
cookies
headers
draftMode
layout.js
、page.js
、route.js
、default.js
、generateMetadata
和generateViewport
中的params
page.js
中的searchParams
为了更容易迁移,这些 API 可以暂时同步访问,但在开发和生产环境中都会显示警告,直到下一个主要版本。 codemod 可用于自动化迁移
npx @next/codemod@canary next-async-request-api .
对于 codemod 无法完全迁移您的代码的情况,请阅读升级指南。我们还提供了一个关于如何将 Next.js 应用程序迁移到新 API 的示例。
增强服务器 Actions 的安全性
Server Actions 是服务器端函数,可以从客户端调用。它们通过在文件顶部添加 'use server'
指令并导出一个异步函数来定义。
即使 Server Action 或实用程序函数没有在代码的其他地方导入,它仍然是一个公开可访问的 HTTP 端点。虽然这种行为在技术上是正确的,但它可能导致此类函数意外暴露。
为了提高安全性,我们引入了以下增强功能
- 死代码消除: 未使用的 Server Action 不会将其 ID 暴露给客户端 JavaScript 包,从而减小包大小并提高性能。
- 安全的操作 ID: Next.js 现在创建难以猜测的、非确定性的 ID,以允许客户端引用和调用 Server Action。这些 ID 在构建之间定期重新计算,以增强安全性。
// app/actions.js
'use server';
// This action **is** used in our application, so Next.js
// will create a secure ID to allow the client to reference
// and call the Server Action.
export async function updateUserAction(formData) {}
// This action **is not** used in our application, so Next.js
// will automatically remove this code during `next build`
// and will not create a public endpoint.
export async function deleteUserAction(formData) {}
您仍然应该将 Server Action 视为公共 HTTP 端点。了解更多关于 保护 Server Action 的信息。
静态路由指示器
Next.js 现在在开发期间显示静态路由指示器,以帮助您识别哪些路由是静态的或动态的。这种可视化提示通过了解页面的渲染方式,使优化性能变得更容易。


您还可以使用 next build
输出查看所有路由的渲染策略。
此更新是我们不断努力增强 Next.js 可观察性的一部分,使开发人员可以更轻松地监控、调试和优化他们的应用程序。我们还在开发专门的开发者工具,更多细节即将公布。
了解更多关于 静态路由指示器的信息,该指示器可以被禁用。
<Form>
组件
新的 <Form>
组件使用 预取、客户端导航 和渐进增强扩展了 HTML <form>
元素。
它适用于导航到新页面的表单,例如引导到结果页面的搜索表单。
import Form from 'next/form';
export default function Page() {
return (
<Form action="/search">
<input name="query" />
<button type="submit">Submit</button>
</Form>
);
}
<Form>
组件具有以下特性:
- 预取:当表单在视图中时,布局 和 加载 UI 会被预取,从而加快导航速度。
- 客户端导航: 提交时,共享布局和客户端状态会被保留。
- 渐进增强: 如果 JavaScript 尚未加载,表单仍然可以通过完整页面导航工作。
以前,实现这些功能需要大量手动样板代码。例如
示例
// Note: This is abbreviated for demonstration purposes.
// Not recommended for use in production code.
'use client'
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
export default function Form(props) {
const action = props.action
const router = useRouter()
useEffect(() => {
// if form target is a URL, prefetch it
if (typeof action === 'string') {
router.prefetch(action)
}
}, [action, router])
function onSubmit(event) {
event.preventDefault()
// grab all of the form fields and trigger a `router.push` with the data URL encoded
const formData = new FormData(event.currentTarget)
const data = new URLSearchParams()
for (const [name, value] of formData) {
data.append(name, value as string)
}
router.push(`${action}?${data.toString()}`)
}
if (typeof action === 'string') {
return <form onSubmit={onSubmit} {...props} />
}
return <form {...props} />
}
了解更多关于 <Form>
组件的信息。
支持 next.config.ts
Next.js 现在支持 TypeScript next.config.ts
文件类型,并提供 NextConfig
类型以实现自动完成和类型安全选项。
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;
了解更多关于 Next.js 中的 TypeScript 支持的信息。
instrumentation.js
(稳定版)
instrumentation
文件及其 register()
API 允许用户接入 Next.js 服务器生命周期,以监控性能、跟踪错误来源,并与 OpenTelemetry 等可观察性库深度集成。
此功能现在是稳定版,可以移除 experimental.instrumentationHook
配置选项。
此外,我们与 Sentry 合作设计了一个新的 onRequestError
钩子,可用于
- 捕获服务器上抛出的所有错误的重要上下文信息,包括:
- 路由器:Pages Router 或 App Router
- 服务器上下文:Server Component、Server Action、Route Handler 或 Middleware
- 将错误报告给您喜欢的可观察性提供商。
export async function onRequestError(err, request, context) {
await fetch('https://...', {
method: 'POST',
body: JSON.stringify({ message: err.message, request, context }),
headers: { 'Content-Type': 'application/json' },
});
}
export async function register() {
// init your favorite observability provider SDK
}
了解更多关于 onRequestError
函数的信息。
开发和构建改进
Server Components HMR
在开发期间,Server 组件在保存时会重新执行。这意味着,对您的 API 端点或第三方服务的任何 fetch
请求也会被调用。
为了提高本地开发性能并减少计费 API 调用的潜在成本,我们现在确保热模块替换 (HMR) 可以重用先前渲染的 fetch
响应。
了解更多关于 Server Components HMR 缓存的信息。
App Router 更快的静态生成
我们优化了静态生成,以缩短构建时间,特别是对于网络请求缓慢的页面。
以前,我们的静态优化过程会渲染页面两次——一次生成用于客户端导航的数据,第二次渲染用于初始页面访问的 HTML。现在,我们重用第一次渲染,去掉了第二次传递,从而减少了工作负载和构建时间。
此外,静态生成 worker 现在在页面之间共享 fetch
缓存。如果 fetch
调用没有选择退出缓存,则其结果将被同一 worker 处理的其他页面重用。这减少了对相同数据的请求数量。
高级静态生成控制(实验性)
我们为更高级的用例添加了对静态生成过程进行更多控制的实验性支持,这些用例将受益于更大的控制。
我们建议坚持当前的默认设置,除非您有特定要求,因为这些选项可能会导致资源使用量增加,并可能由于并发性增加而导致内存不足错误。
const nextConfig = {
experimental: {
// how many times Next.js will retry failed page generation attempts
// before failing the build
staticGenerationRetryCount: 1
// how many pages will be processed per worker
staticGenerationMaxConcurrency: 8
// the minimum number of pages before spinning up a new export worker
staticGenerationMinPagesPerWorker: 25
},
}
export default nextConfig;
了解更多关于 静态生成选项的信息。
自托管的改进
当自托管应用程序时,您可能需要更多地控制 Cache-Control
指令。
一个常见的情况是控制为 ISR 页面发送的 stale-while-revalidate
期间。我们实现了两项改进:
- 您现在可以在
next.config
中配置expireTime
值。这以前是experimental.swrDelta
选项。 - 更新了默认值为一年,确保大多数 CDN 可以完全按照预期应用
stale-while-revalidate
语义。
我们也不再使用默认值覆盖自定义 Cache-Control
值,从而允许完全控制并确保与任何 CDN 设置的兼容性。
最后,我们改进了自托管时的图像优化。以前,我们建议您安装 sharp
以优化 Next.js 服务器上的图像。这个建议有时会被忽略。在 Next.js 15 中,您不再需要手动安装 sharp
—— 当使用 next start
或以 独立输出模式 运行时,Next.js 将自动使用 sharp
。
要了解更多信息,请观看我们关于自托管 Next.js 的新 演示和教程视频。
ESLint 9 支持
Next.js 15 还引入了对 ESLint 9 的支持,此前 ESLint 8 已于 2024 年 10 月 5 日停止生命周期。
为了确保平稳过渡,Next.js 保持向后兼容,这意味着您可以继续使用 ESLint 8 或 9。
如果您升级到 ESLint 9,并且我们检测到您尚未采用 新的配置格式,Next.js 将自动应用 ESLINT_USE_FLAT_CONFIG=false
应急方案,以简化迁移。
此外,当运行 next lint
时,将删除已弃用的选项,如 —ext
和 —ignore-path
。请注意,ESLint 最终将在 ESLint 10 中禁用这些旧配置,因此我们建议您尽快开始迁移。
有关这些更改的更多详细信息,请查看 迁移指南。
作为此更新的一部分,我们还将 eslint-plugin-react-hooks
升级到 v5.0.0
,其中引入了 React Hooks 使用的新规则。您可以在 eslint-plugin-react-hooks@5.0.0 的变更日志 中查看所有更改。
其他更改
- 所有先前在 RC 1 博客文章 中描述的更改
- [重大变更] 我们已弃用在 App Router 中导出
export const runtime = "experimental-edge"
。用户现在应该切换到export const runtime = "edge"
。我们添加了一个 codemod 来执行此操作 (PR) - [Breaking 变更] 在渲染期间调用
revalidateTag
和revalidatePath
现在会抛出错误 (PR) - [Breaking 变更]
instrumentation.js
和middleware.js
文件现在将使用捆绑的 React 包 (PR) - [Breaking 变更] 最低要求的 Node.js 版本已更新至 18.18.0 (PR)
- [Breaking 变更]
next/dynamic
: 已弃用的suspense
prop 已被移除,并且当组件在 App Router 中使用时,它将不再插入空的 Suspense 边界 (PR) - [Breaking 变更] 当在 Edge Runtime 上解析模块时,将不会应用
worker
模块条件 (PR) - [Breaking 变更] 禁止在 Server Components 中使用带有
next/dynamic
的ssr: false
选项 (PR) - [Improvements 改进]
outputFileTracingRoot
,outputFileTracingIncludes
和outputFileTracingExcludes
已从实验性升级为稳定版 (PR) - [Improvements 改进] 避免将全局 CSS 文件与树中更深层次的 CSS 模块文件合并 (PR)
- [Improvements 改进] 缓存处理程序可以通过
NEXT_CACHE_HANDLER_PATH
环境变量指定 (PR) - [Improvements 改进] Pages Router 现在同时支持 React 18 和 React 19 (PR)
- [Improvements 改进] 错误覆盖层现在显示一个按钮,用于在启用检查器时复制 Node.js 检查器 URL (PR)
- [Improvements 改进] App Router 上的客户端预取现在使用
priority
属性 (PR) - [Improvements 改进] Next.js 现在提供
unstable_rethrow
函数,用于在 App Router 中重新抛出 Next.js 内部错误 (PR) - [Improvements 改进]
unstable_after
现在可以在静态页面中使用 (PR) - [Improvements 改进] 如果在 SSR 期间使用
next/dynamic
组件,则 chunk 将会被预取 (PR) - [Improvements 改进] App Router 现在支持
esmExternals
选项 (PR) - [Improvements 改进]
experimental.allowDevelopmentBuild
选项可用于允许NODE_ENV=development
与next build
一起用于调试目的 (PR) - [Improvements 改进] Server Action 转换现在在 Pages Router 中禁用 (PR)
- [Improvements 改进] 构建工作进程现在将在退出时阻止构建挂起 (PR)
- [Improvements 改进] 当从 Server Action 重定向时,重新验证现在将正确应用 (PR)
- [Improvements 改进] 动态参数现在可以在 Edge Runtime 上的并行路由中正确处理 (PR)
- [Improvements 改进] 静态页面现在将在初始加载后遵守 staleTime (PR)
- [Improvements 改进]
vercel/og
已更新,包含内存泄漏修复 (PR) - [Improvements 改进] Patch timings 已更新,允许使用类似
msw
的包进行 API 模拟 (PR)
贡献者
Next.js 是超过 3,000 位个人开发者以及我们在 Vercel 的核心团队共同努力的成果。本次发布由以下人员为您带来:
- Next.js 团队:Andrew、Hendrik、Janka、Jiachi、Jimmy、Jiwon、JJ、Josh、 Sam、Sebastian、 Sebbie、Shu、Wyatt 和 Zack。
- Turbopack 团队:Alex、 Benjamin、 Donny、Maia、Niklas、Tim、Tobias 和 Will。
- Next.js 文档 团队:Delba、Rich、Ismael 和 Lee。
非常感谢 @huozhi, @shuding, @wyattjoh, @PaulAsjes, @mcnaveen, @timneutkens, @stipsan, @aktoriukas, @sirTangale, @greatvivek11, @sokra, @anatoliik-lyft, @wbinnssmith, @coltonehrman, @hungdoansy, @kxlow, @ztanner, @manovotny, @leerob, @ryota-murakami, @ijjk, @pnutmath, @feugy, @Jeffrey-Zutt, @wiesson, @eps1lon, @devjiwonchoi, @Ethan-Arrowood, @kenji-webdev, @domdomegg, @samcx, @Jaaneek, @evanwinter, @kdy1, @balazsorban44, @feedthejim, @ForsakenHarmony, @kwonoj, @delbaoliveira, @xiaohanyu, @dvoytenko, @bobaaaaa, @bgw, @gaspar09, @souporserious, @unflxw, @kiner-tang, @Ehren12, @EffectDoplera, @IAmKushagraSharma, @Auxdible, @sean-rallycry, @jeanmax1me, @unstubbable, @NilsJacobsen, @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, @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, @tokkiyaa, @arlyon, @lorensr, @Juneezee, @Sayakie, @IGassmann, @bosconian-dynamics, @phryneas, @akazwz, @atik-persei, @shubh73, @alpedia0, @chogyejin, @notomo, @ArnoldVanN, @dhruv-kaushik, @kevva, @Kahitar, @anay-208, @boris-szl, @devnyxie, @LorisSigrist, @M-YasirGhaffar, @Lada496, @kippmr, @torresgol10, @pkiv, @Netail, @jontewks, @ArnaudFavier, @chrisjstott, @mratlamwala, @mayank1513, @karlkeefer, @kshehadeh, @Marukome0743, @a89529294, @anku255, @KeisukeNagakawa, @andrii-bodnar, @aldosch, @versecafe, @steadily-worked, @cfrank, @QiuranHu, @farsabbutt, @joostmeijles, @saltcod, @archanaagivale30, @crutchcorn, @crebelskydico, @Maaz-Ahmed007, @jophy-ye, @remcohaszing, @JoshuaKGoldberg, @creativoma, @GyoHeon, @SukkaW, @MaxLeiter, @neila-a, @stylessh, @Teddir, @ManuLpz4, @Julian-Louis, @syi0808, @mert-duzgun, @amannn, @MonstraG, @hamirmahal, @tariknh, @Kikobeats, @LichuAcu, @Kuboczoch, @himself65, @Sam-Phillemon9493, @Shruthireddy04, @Hemanshu-Upadhyay, @timfuhrmann, @controversial, @pathliving, @mischnic, @mauroaccornero, @NavidNourani, @allanchau, @ekremkenter, @yurivangeffen, @gnoff, @darthmaim, @gdborton, @Willem-Jaap, @KentoMoriwaki, @TrevorSayre, @marlier, @Luluno01, @xixixao, @domin-mnd, @niketchandivade, @N2D4, @kjugi, @luciancah, @mud-ali, @codeSTACKr, @luojiyin1987, @mehmetozguldev, @ronanru, @tknickman, @joelhooks, @khawajaJunaid, @rubyisrust, @abdull-haseeb, @bewinsnw, @housseindjirdeh, @li-jia-nan, @aralroca, @s-ekai, @ah100101, @jantimon, @jordienr, @iscekic, @Strift, @slimbde, @nauvalazhar, @HughHzyb, @guisehn, @wesbos, @OlyaPolya, @paarthmadan, @AhmedBaset, @dineshh-m, @avdeev, @Bhavya031, @MildTomato, @Bjornnyborg, @amikofalvy, @yosefbeder, @kjac, @woutvanderploeg, @Ocheretovich, @ProchaLu, @luismiramirez, @omahs, @theoludwig, @abhi12299, @sommeeeer, @lumirlumir, @royalfig, @iampoul, @molebox, @txxxxc, @zce, @mamuso, @kahlstrm, @vercel-release-bot, @zhawtof, @PapatMayuri, @PlagueFPS, @IDNK2203, @jericopulvera, @liby, @CannonLock, @timfish, @whatisagi, @none23, @haouvw, @Pyr33x, @SouthLink, @frydj, @CrutchTheClutch, @sleevezip, @r34son, @yunsii, @md-rejoyan-islam, @kartheesan05, @nattui, @KonkenBonken, @weicheng95, @brekk, @Francoscopic, @B33fb0n3, @ImDR, @nurullah, @hdodov, @ebCrypto, @soedirgo, @floriangosse, @Tim-Zj, @raeyoung-kim, @erwannbst, @DerTimonius, @hirotomoyamada, @Develliot, @chandanpasunoori, @vicb, @ankur-dwivedi, @kidonng, @baeharam, @AnaTofuZ, @coderfin, @xugetsu, @alessiomaffeis, @kutsan, @jordyfontoura, @sebmarkbage, @tranvanhieu01012002, @jlbovenzo, @Luk-z, @jaredhan418, @bangseongbeom, @penicillin0, @neoFinch, @DeepakBalaraman, @Manoj-M-S, @Unsleeping, @lonr, @Aerilym, @ytori, @acdlite, @actopas, @n-ii-ma, @adcichowski, @mobeigi, @JohnGemstone, 和 @jjm2317 感谢各位的帮助!