Back返回博客

Next.js 15.1

Next.js 15.1 引入了对 React 19 的稳定支持、改进的错误调试功能、新的实验性授权 API 等特性。

Next.js 15.1 带来了核心升级、新 API 和开发者体验改进。主要更新包括:

立即升级,或通过以下命令开始使用:

Terminal
# 使用自动化升级 CLI
npx @next/codemod@canary upgrade latest
 
# ...或手动升级
npm install next@latest react@latest react-dom@latest
 
# ...或创建新项目
npx create-next-app@latest

React 19(稳定版)

Next.js 15.1 现已全面支持 React 19:

  • 对于 Pages Router:无需使用候选版或 Canary 版本即可直接使用 React 19 稳定版,同时保持对 React 18 的兼容。
  • 对于 App Router:将继续内置 React Canary 版本。这些版本包含所有 React 19 稳定版变更,以及框架验证中的新特性。

自 Next.js 15 发布以来,React 19 的重要新增功能是"兄弟组件预热"。

有关 React 19 更新的完整概述,请参阅官方 React 19 博客文章

改进的错误调试

我们改进了 Next.js 的错误调试功能,确保您能快速定位问题根源,无论错误出现在终端、浏览器还是调试器中。这些改进同时适用于 Webpack 和 Turbopack(已在 Next.js 15 中稳定)。

源码映射增强

通过改进源码映射的使用,现在能更轻松地追溯错误源头。我们实现了源码映射的 ignoreList 属性,允许 Next.js 隐藏外部依赖的堆栈帧,使应用代码成为主要焦点。

为获得更精确的方法名源码映射,我们建议采用 Turbopack(现已稳定),它在源码映射处理和检测方面比 Webpack 更优秀。

给库作者的建议:发布库时建议填充源码映射中的 ignoreList 属性,特别是当它们被配置为外部依赖时(例如在 serverExternalPackages 配置中)。

折叠堆栈帧

我们改进了堆栈帧折叠逻辑,以突出显示代码中最相关的部分。

  • 在浏览器和错误覆盖层中:默认隐藏第三方依赖的堆栈帧,聚焦于您的应用代码。可通过点击开发工具或覆盖层中的"显示被忽略帧"来查看隐藏帧。
  • 在终端中:第三方依赖帧也默认折叠,错误格式现在与浏览器输出保持一致。错误会在浏览器中重放,确保开发时不会遗漏重要信息。

增强的性能分析

内置浏览器分析器也能识别被忽略的堆栈帧。这使得分析应用性能更容易,让您能准确定位代码中的慢速函数,而不会被外部库干扰。

Edge 运行时的改进

使用 Edge 运行时,现在开发环境中错误显示保持一致,确保无缝调试。此前,日志错误仅包含消息而不包含堆栈。

改进前后对比

终端 改进前

Terminal
 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

终端 改进后

Terminal
 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'
}

错误覆盖层 改进前

Next.js 15.1 版本前的错误覆盖层示例

错误覆盖层 改进后

Next.js 15.1 版本后的错误覆盖层示例

这些改进使错误更清晰直观,让您能将时间更多投入应用构建而非调试。

我们也很高兴地宣布,错误覆盖层的重新设计 UI 将在后续版本中推出。

after(稳定版)

after() API 自 Next.js 15 首个候选版引入后现已稳定。

after() 提供了一种方式,在主响应流式传输给用户后执行日志记录、分析等任务,而不会阻塞主响应。

关键变更

自引入以来,我们已稳定 after() 并解决了以下反馈:

  • 改进了对自托管 Next.js 服务器的支持。
  • 修复了 after() 与其他 Next.js 功能交互时的错误。
  • 增强了可扩展性,使其他平台能注入自己的 waitUntil() 原语来支持 after()
  • 支持在服务器操作和路由处理程序中使用运行时 API,如 cookies()headers()
app/layout.js
import { after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // 次要任务
  after(() => {
    log();
  });
 
  // 主要任务
  return <>{children}</>;
}

在文档中阅读更多关于 after API 的信息及如何使用它。

forbiddenunauthorized(实验性)

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 文件中启用:

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();
 
  // 检查用户是否具有 'admin' 角色
  if (session.role !== 'admin') {
    forbidden();
  }
 
  // 为授权用户渲染管理页面
  return <h1>Admin Page</h1>;
}

创建自定义错误页面

要自定义错误页面,创建以下文件:

app/forbidden.tsx
import Link from 'next/link';
 
export default function Forbidden() {
  return (
    <div>
      <h2>禁止访问</h2>
      <p>您无权访问此资源。</p>
      <Link href="/">返回首页</Link>
    </div>
  );
}
app/unauthorized.tsx
import Link from 'next/link';
 
export default function Unauthorized() {
  return (
    <div>
      <h2>未经授权</h2>
      <p>请登录以访问此页面。</p>
      <Link href="/login">前往登录</Link>
    </div>
  );
}

我们要感谢 Clerk 通过 PR 提议此功能并协助我们原型设计 API。在 15.2 版本稳定此功能前,我们计划为 API 添加更多功能和改进以支持更广泛的用例。

阅读 unauthorizedforbidden API 文档了解更多详情。

其他变更

  • [功能]create-next-app 中使用 ESLint 9 (PR)
  • [功能] 将最大缓存标签数增至 128 (PR)
  • [功能] 添加禁用实验性 CssChunkingPlugin 的选项 (PR)
  • [功能] 添加实验性 CSS 内联支持 (PR)
  • [改进] 静默 Sass legacy-js-api 警告 (PR)
  • [改进] 修复使用重写时的未处理拒绝 (PR)
  • [改进] 确保 webpack 工作进程失败时父进程退出 (PR)
  • [改进] 修复全捕获路由的路由拦截 (PR)
  • [改进] 修复请求去重中的响应克隆问题 (PR)
  • [改进] 修复多个根布局间的服务器操作重定向 (PR)
  • [改进] 支持为 Turbopack 兼容性提供字符串形式的 MDX 插件 (PR)

贡献者

Next.js 是超过 3,000 名开发者共同工作的成果。本版本由以下人员共同打造:

特别感谢 @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 的贡献!