跳到内容
返回博客

2024年12月10日,星期二

Next.js 15.1

发布者

Next.js 15.1 带来了核心升级、新的 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 稳定版,而无需使用发布候选版或 Canary 版,并继续支持 React 18。
  • 对于 App Router:我们将继续提供内置的 React Canary 版本。这些版本包括所有稳定的 React 19 更改,以及在新的 React 版本发布之前,在框架中进行验证的更新功能。

自 Next.js 15 发布以来,React 19 的一个重要新增功能是“兄弟预热”。

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

改进的错误调试

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

源映射增强功能

现在,通过改进的源映射使用,错误更容易追溯到其源头。我们实现了源映射的ignoreList属性,这允许 Next.js 隐藏外部依赖项的堆栈帧,使您的应用程序代码成为主要焦点。

为了更准确地映射方法名,我们建议采用 Turbopack(现已稳定),它比 Webpack 具有更好的源映射处理和检测能力。

对于库作者:我们建议在发布库时填充源映射中的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'
}

错误覆盖层 之前

An example of the Next.js error overlay before version 15.1
Next.js 15.1 版本之前的错误覆盖层示例

错误覆盖层 之后

An example of the Next.js error overlay after version 15.1
Next.js 15.1 版本之后的错误覆盖层示例

这些改进使得错误更清晰、更直观,让您可以将时间集中于构建应用程序而非调试。

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

after (稳定版)

在 Next.js 15 RC 的首次引入之后,after() API 现已稳定。

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 }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

阅读文档以了解有关 after API 及其使用方法的更多信息。

forbiddenunauthorized (实验性)

Next.js 15.1 包含了两个实验性 API,forbidden()unauthorized(),它们是基于社区反馈而开发的。

我们期待您的反馈 — 请在您的开发环境中尝试并在此讨论帖中分享您的想法。

概述

如果您熟悉 App Router,您可能使用过 notFound() 来触发 404 行为以及可定制的 not-found.tsx 文件。在 15.1 版本中,我们将此方法扩展到授权错误:

forbidden() 通过 forbidden.tsx 触发403 错误并显示可定制的 UI。

unauthorized() 通过 unauthorized.tsx 触发401 错误并显示可定制的 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();
 
  // 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>;
}

创建自定义错误页面

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

app/forbidden.tsx
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>
  );
}
app/unauthorized.tsx
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通过拉取请求提出此功能并协助我们进行 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 worker 失败时父进程退出 (PR)
  • [改进] 修复了包罗万象路由上的路由拦截问题 (PR)
  • [改进] 修复了请求去重中的响应克隆问题 (PR)
  • [改进] 修复了多个根布局之间服务器动作重定向的问题 (PR)
  • [改进] 支持将 MDX 插件作为字符串提供以实现 Turbopack 兼容性 (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 的帮助!