跳至内容
返回博客

2024年5月23日,星期四

Next.js 15 RC

发布者

Next.js 15 发布候选版本 (RC) 现已推出。此早期版本允许您在即将发布的稳定版本之前测试最新功能。

立即试用 Next.js 15 RC

终端
npm install next@rc react@rc react-dom@rc

React 19 RC

Next.js App Router 建立在 React 的 框架金丝雀通道 上,这使得开发人员能够在 v19 版本发布之前使用和提供关于这些新 React API 的反馈。

Next.js 15 RC 现在支持 React 19 RC,其中包括客户端和服务器(如 Actions)的新功能。

阅读 Next.js 15 升级指南React 19 升级指南,并观看 React Conf 主题演讲 以了解更多信息。

注意: 一些第三方库可能尚未与 React 19 兼容。

React 编译器(实验性)

Meta 的 React 团队创建了一个新的实验性编译器,即 React 编译器。编译器通过其对普通 JavaScript 语义和 React 规则 的理解,深入了解您的代码,从而可以为您的代码添加自动优化。编译器减少了开发人员必须通过 useMemouseCallback 等 API 手动执行记忆化的次数,从而使代码更简单、更易于维护,并且更不容易出错。

通过 Next.js 15,我们添加了对 React 编译器 的支持。

安装 babel-plugin-react-compiler

终端
npm install babel-plugin-react-compiler

然后,在 next.config.js 中添加 experimental.reactCompiler 选项

next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
module.exports = nextConfig;

或者,您可以将编译器配置为按如下方式以“选择加入”模式运行

next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: {
      compilationMode: 'annotation',
    },
  },
};
 
module.exports = nextConfig;

注意: 目前,只能通过 Babel 插件在 Next.js 中使用 React 编译器,这可能会导致构建时间变慢。

了解有关 React 编译器可用的 Next.js 配置选项 的更多信息。

水合错误改进

Next.js 14.1 对错误消息和水合错误进行了改进。Next.js 15 通过添加改进的水合错误视图继续在此基础上构建。水合错误现在显示错误的源代码,以及有关如何解决问题的建议。

例如,这是 Next.js 14.1 中之前的水合错误消息

Hydration error message in Next.js 14.1

Next.js 15 RC 已对此进行了改进,如下所示

Hydration error message improved in 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' 以覆盖 Layout 或 Page 中的所有 fetch 请求,使其使用 force-cache,除非它们明确指定自己的 cache 选项。

默认情况下,GET 路由处理程序不再被缓存

在 Next 14 中,使用 GET HTTP 方法的路由处理程序默认情况下会被缓存,除非它们使用了动态函数或动态配置选项。在 Next.js 15 中,GET 函数**默认不会被缓存**。

您仍然可以通过使用静态路由配置选项(例如 export dynamic = 'force-static')选择加入缓存。

特殊的路由处理程序,如 sitemap.tsopengraph-image.tsxicon.tsx,以及其他 元数据文件,默认情况下仍然保持静态,除非它们使用动态函数或动态配置选项。

客户端路由缓存默认不再缓存页面组件

在 Next.js 14.2.0 中,我们引入了实验性的 staleTimes 标志,以允许自定义配置 路由缓存

在 Next.js 15 中,此标志仍然可以使用,但我们正在将默认行为更改为对页面片段具有 0staleTime。这意味着,当您在应用程序中导航时,客户端将始终反映页面组件(作为导航的一部分而处于活动状态)的最新数据。但是,仍然有一些重要的行为保持不变。

  • 共享布局数据不会从服务器重新获取,以继续支持 部分渲染
  • 后退/前进导航仍将从缓存中恢复,以确保浏览器可以恢复滚动位置。
  • Loading.js 将保留在缓存中 5 分钟(或 staleTimes.static 配置的值)。

您可以通过设置以下配置选择加入以前的客户端路由缓存行为:

next.config.ts
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 路由配置选项,用于将特定的 Layout 和 Page 选择加入 PPR。

app/page.jsx
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'

next.config.ts
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 中。

next.config.ts
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 并采用了新的设计。

New design for create-next-app in Next.js 15 RC

运行 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 选择退出特定的包(如果需要)。

next.config.ts
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)
  • [重大更改] 中间件:应用 react-server 条件以限制不推荐使用的 React API 导入 (PR)
  • [重大更改] next/font:删除了对外部 @next/font 包的支持 (PR)
  • [重大更改] next/font:删除了 font-family 哈希 (PR)
  • [重大更改] 缓存:force-dynamic 现在将 no-store 设为 fetch 缓存的默认值 (PR)
  • [重大更改] 配置:默认启用 swcMinify (PR)、missingSuspenseWithCSRBailout (PR) 和 outputFileTracing (PR) 行为,并删除已弃用的选项。
  • [重大更改] 删除 Speed Insights 的自动检测 (现在必须使用专用的 @vercel/speed-insights 包) (PR)
  • [重大更改] 删除动态站点地图路由的 .xml 扩展名,并在开发和生产环境之间统一站点地图 URL (PR)
  • [改进] 元数据:在 Vercel 上托管时,更新了 metadataBase 的环境变量回退 (PR)
  • [改进] 修复了来自 optimizePackageImports 的混合命名空间和命名导入的 tree-shaking 问题 (PR)
  • [改进] 并行路由:为不匹配的通配符路由提供所有已知参数 (PR)
  • [改进] 配置 bundlePagesExternals 现在已稳定并重命名为 bundlePagesRouterDependencies
  • [改进] 配置 serverComponentsExternalPackages 现在已稳定并重命名为 serverExternalPackages
  • [改进] create-next-app:新项目默认忽略所有 .env 文件 (PR)
  • [文档] 改进身份验证文档 (PR)

  • [文档] @next/env 包 (PR)

要了解更多信息,请查看 升级指南

贡献者

Next.js 是超过 3000 位独立开发者、谷歌和 Meta 等行业合作伙伴以及我们在 Vercel 的核心团队共同努力的结果。此版本由以下人员贡献:

非常感谢 @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 的帮助!