2024 年 12 月 10 日,星期二
Next.js 15.1
发布者Next.js 15.1 带来了核心升级、新 API 和开发者体验的改进。主要更新包括
- React 19 (稳定版):Pages Router 和 App Router 均已正式支持 React 19。
- 改进的错误调试:增强了 DX,并为浏览器和终端提供了更好的源映射。
after
(稳定版):新的 API,用于在响应完成流式传输后执行代码。forbidden
/unauthorized
(实验性):新的 API,用于实现更细粒度的身份验证错误处理。
立即升级,或开始使用
# Use the automated upgrade CLI
npx @next/codemod@canary upgrade latest
# ...or upgrade manually
npm install next@latest react@latest react-dom@latest
# ...or start a new project
npx create-next-app@latest
React 19 (稳定版)
Next.js 15.1 现在完全支持 React 19
- 对于 Pages Router:您现在可以使用 React 19 稳定版,无需 Release Candidate 或 Canary 版本,同时继续支持 React 18。
- 对于 App Router:我们将继续提供内置的 React Canary 版本。这些版本包括所有 React 19 稳定版更改,以及在新的 React 版本发布之前,框架中正在验证的较新功能。
自 Next.js 15 版本发布以来,React 19 的一个重大新增功能是“sibling pre-warming”。
有关 React 19 更新的全面概述,请参阅官方 React 19 博客文章。
改进的错误调试
我们改进了 Next.js 中的错误调试,确保您可以快速定位问题的根源,无论它们出现在终端、浏览器还是附加的调试器中。这些增强功能适用于 Webpack 和 Turbopack(Turbopack 在 Next.js 15 中已稳定)。
源映射增强
通过改进源映射的使用,现在可以更轻松地将错误追溯到其来源。我们实现了 源映射的 ignoreList
属性,这使 Next.js 可以隐藏外部依赖项的堆栈帧,从而使您的应用程序代码成为主要焦点。
为了更准确地映射方法名称的源,我们建议采用 Turbopack(现已稳定),它在 Webpack 上改进了源映射的处理和检测。
对于库作者:我们建议在发布库时填充 sourcemap 中的
ignoreList
属性,特别是当它们配置为外部库时(例如,在serverExternalPackages
配置中)。
折叠的堆栈帧
我们改进了折叠堆栈帧的逻辑,以突出显示代码中最相关的部分。
- 在浏览器和错误覆盖层中:默认情况下,来自第三方依赖项的堆栈帧被隐藏,重点放在您的应用程序代码上。您可以通过单击开发者工具或覆盖层中的“显示忽略的帧”来显示隐藏的帧。
- 在终端中:第三方依赖项帧也默认折叠,并且错误格式现在与浏览器输出对齐,以实现一致的调试体验。错误会在浏览器中重播,以确保您在开发期间不会错过重要信息(如果您需要完整的堆栈跟踪)。
增强的性能分析
内置浏览器性能分析器也识别忽略的堆栈帧。这使分析应用程序的性能变得更加容易,使您可以精确定位代码中的慢速函数,而不会受到外部库的干扰。
通过 Edge Runtime 改进
当使用 Edge runtime 时,错误现在在不同的开发环境中显示一致,确保无缝调试。以前,记录的错误只会包含消息,而不会包含堆栈。
之前和之后
终端 之前
⨯ app/page.tsx (6:11) @ eval
⨯ Error: boom
at eval (./app/page.tsx:12:15)
at Page (./app/page.tsx:11:74)
at AsyncLocalStorage.run (node:async_hooks:346:14)
at stringify (<anonymous>)
at AsyncLocalStorage.run (node:async_hooks:346:14)
at AsyncResource.runInAsyncScope (node:async_hooks:206:9)
digest: "380744807"
4 | export default function Page() {
5 | const throwError = myCallback(() => {
> 6 | throw new Error('boom')
| ^
7 | }, [])
8 |
9 | throwError()
GET / 500 in 2354ms
终端 之后
⨯ Error: boom
at eval (app/page.tsx:6:10)
at Page (app/page.tsx:5:32)
4 | export default function Page() {
5 | const throwError = myCallback(() => {
> 6 | throw new Error('boom')
| ^
7 | }, [])
8 |
9 | throwError() {
digest: '225828171'
}
错误覆盖层 之前


错误覆盖层 之后


这些改进使错误更加清晰和直观,让您可以将时间集中在构建应用程序而不是调试上。
我们还很高兴地宣布,即将推出的版本将为错误覆盖层引入重新设计的 UI。
after
(稳定版)
after()
API 在 Next.js 15 RC 第一个版本中引入后,现在已稳定。
after()
提供了一种在响应完成流式传输到用户后执行诸如日志记录、分析和其他系统同步等任务的方法,而不会阻塞主要响应。
主要变更
自引入以来,我们稳定了 after()
并解决了包括以下反馈
- 改进了对 自托管 Next.js 服务器的支持。
- 修复了
after()
与其他 Next.js 功能交互的场景的 错误。 - 增强了可扩展性,使其他平台能够注入自己的
waitUntil()
原语来支持after()
。 - 支持运行时 API,例如服务器操作和路由处理程序中的
cookies()
和headers()
。
import { after } from 'next/server';
import { log } from '@/app/utils';
export default function Layout({ children }) {
// Secondary task
after(() => {
log();
});
// Primary task
return <>{children}</>;
}
阅读文档以了解有关 after
API 以及如何在文档中利用它的更多信息。
forbidden
和 unauthorized
(实验性)
Next.js 15.1 包括两个实验性 API:forbidden()
和 unauthorized()
,它们基于社区反馈。
我们很乐意听取您的反馈——请在您的开发环境中试用,并在此讨论帖中分享您的想法。
概述
如果您熟悉 App Router,您可能已经使用过 notFound()
来触发 404 行为,并结合可自定义的 not-found.tsx
文件。在 15.1 版本中,我们将这种方法扩展到授权错误
• forbidden()
触发 403 错误,可通过 forbidden.tsx
自定义 UI。
• unauthorized()
触发 401 错误,可通过 unauthorized.tsx
自定义 UI。
须知: 与
notFound()
错误一样,如果在发送初始响应头后触发错误,则状态代码将为200
。了解更多。
启用该功能
由于此功能仍处于实验阶段,因此您需要在 next.config.ts
文件中启用它
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
experimental: {
authInterrupts: true,
},
};
export default nextConfig;
注意:
next.config.ts
支持在 Next.js 15 中引入。了解更多。
使用 forbidden()
和 unauthorized()
您可以在服务器操作、服务器组件、客户端组件或路由处理程序中使用 forbidden()
和 unauthorized()
。这是一个示例
import { verifySession } from '@/app/lib/dal';
import { forbidden } from 'next/navigation';
export default async function AdminPage() {
const session = await verifySession();
// Check if the user has the 'admin' role
if (session.role !== 'admin') {
forbidden();
}
// Render the admin page for authorized users
return <h1>Admin Page</h1>;
}
创建自定义错误页面
要自定义错误页面,请创建以下文件
import Link from 'next/link';
export default function Forbidden() {
return (
<div>
<h2>Forbidden</h2>
<p>You are not authorized to access this resource.</p>
<Link href="/">Return Home</Link>
</div>
);
}
import Link from 'next/link';
export default function Unauthorized() {
return (
<div>
<h2>Unauthorized</h2>
<p>Please log in to access this page.</p>
<Link href="/login">Go to Login</Link>
</div>
);
}
我们要感谢 Clerk 通过 PR 提出此功能并协助我们进行 API 原型设计。在我们于 15.2 版本中稳定此功能之前,我们计划为 API 添加更多功能和改进,以支持更广泛的用例。
阅读文档以获取有关 unauthorized
和 forbidden
API 的更多详细信息。
其他更改
- [功能] 在
create-next-app
中使用 ESLint 9 (PR) - [功能] 将最大缓存标签增加到 128 个 (PR)
- [功能] 添加一个选项以禁用实验性的 CssChunkingPlugin (PR)
- [功能] 添加实验性的 CSS 内联支持 (PR)
- [改进] 消除 Sass
legacy-js-api
警告 (PR) - [改进] 修复使用 rewrites 时未处理的拒绝 (PR)
- [改进] 确保在 webpack worker 失败时父进程退出 (PR)
- [改进] 修复了 catch-all 路由上的路由拦截 (PR)
- [改进] 修复了请求去重中的响应克隆问题 (PR)
- [改进] 修复了多个根布局之间的服务器操作重定向 (PR)
- [改进] 支持将 MDX 插件作为字符串提供,以实现 Turbopack 兼容性 (PR)
贡献者
Next.js 是超过 3,000 位个人开发者的共同努力成果。此版本由以下人员为您带来
- Next.js 团队:Andrew、Hendrik、Janka、Jiachi、Jimmy、Jiwon、JJ、Josh、Jude、Sam、Sebastian、Sebbie、Wyatt 和 Zack。
- Turbopack 团队: Alex, Benjamin, Donny, Maia, Niklas, Tim, Tobias, 和 Will。
- Next.js Docs 团队: Delba, Rich, Ismael, 和 Lee。
非常感谢 @sokra, @molebox, @delbaoliveira, @eps1lon, @wbinnssmith, @JamBalaya56562, @hyungjikim, @adrian-faustino, @mottox2, @lubieowoce, @bgw, @mknichel, @wyattjoh, @huozhi, @kdy1, @mischnic, @ijjk, @icyJoseph, @acdlite, @unstubbable, @gaojude, @devjiwonchoi, @cena-ko, @lforst, @devpla, @samcx, @styfle, @ztanner, @Marukome0743, @timneutkens, @JeremieDoctrine, @ductnn, @karlhorky, @reynaldichernando, @chogyejin, @y-yagi, @philparzer, @alfawal, @Rhynden, @arlyon, @MJez29, @Goodosky, @themattmayfield, @tobySolutions, @kevinmitch14, @leerob, @emmanuelgautier, @mrhrifat, @lid0a, @boar-is, @nisabmohd, @PapatMayuri, @ovogmap, @Reflex2468, @LioRael, @betterthanhajin, @HerringtonDarkholme, @bpb54321, @ahmoin, @Kikobeats, @abdelrahmanAbouelkheir, @lumirlumir, @yeeed711, @petter, 和 @suu3 的帮助!