跳至内容
返回博客

2024年10月15日,星期二

Next.js 15 RC 2

发布者

继 5 月份发布第一个 Next.js 15 发布候选版本 的公告后, 我们一直在根据您的反馈准备第二个发布候选版本。以下是我们一直在努力的方向

立即体验 Next.js 15 发布候选版本 (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

注意:此发布候选版本包含来自 先前 RC 版本 的所有更改。

使用 codemod CLI 实现平滑升级

我们为每次主要的 Next.js 版本发布都提供了代码修改工具(自动代码转换),以帮助自动化升级重大更改。

为了使升级更加顺畅,我们发布了一个增强的 codemod CLI

npx @next/codemod@canary upgrade rc

此工具可帮助您将代码库升级到最新的稳定版或预发布版本。CLI 将更新您的依赖项,显示可用的代码修改工具,并指导您完成应用它们的过程。命令行上指定的 dist 标记(@rc@canary 等)决定了要升级到的版本。

详细了解 Next.js 代码修改工具

开发环境中的 Turbopack

用于本地开发的 Turbopack 将在 Next.js 15 的正式版本中稳定下来,同时保持选择加入。您今天可以通过运行以下命令来试用它

next dev --turbo

感谢数千名开发人员在整个 Turbopack 测试版和发布候选版阶段参与测试、报告问题和验证修复,我们解决了 54 个 GitHub 问题,自第一个 Next.js 15 发布候选版本以来。除了社区的努力之外,我们在 vercel.comv0.devnextjs.org 上进行的内部测试帮助我们识别了许多其他改进。

在过去的三个月里,我们专注于优化冷编译性能。与之前的版本相比,我们看到了

  • 内存使用量 **减少了 25-35%**。
  • 对于包含数千个模块的大型页面,编译速度 **提高了 30-50%**。

我们将在未来的版本中继续优化这些方面。

展望未来,Turbopack 团队在持久缓存、内存使用量减少以及 Turbopack for next build方面取得了重大进展,测试通过率已达到 96%

注意:请查看 Turbopack 支持和不支持的功能 的完整列表。

异步请求 API(重大变更)

在传统的服务器端渲染中,服务器会在收到请求后才会开始渲染任何内容。但是,并非所有组件都依赖于特定于请求的数据,因此无需等待请求来渲染它们。理想情况下,服务器会在请求到达之前尽可能多地准备工作。为了实现这一点,并为未来的优化奠定基础,我们需要知道何时需要等待请求。

因此,我们正在将依赖于特定于请求的数据(例如 headerscookiesparamssearchParams)的 API 转换为异步

import { cookies } from 'next/headers';
 
export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
 
  // ...
}

这是一个重大变更,会影响以下 API

  • cookies
  • headers
  • draftMode
  • paramslayout.jspage.jsroute.jsdefault.jsgenerateMetadatagenerateViewport
  • searchParamspage.js

为了更轻松地迁移,这些 API 可以暂时以同步方式访问,但在开发和生产环境中会显示警告,直到下一个主要版本发布。可以使用 codemod 自动化迁移过程。

npx @next/codemod@canary next-async-request-api .

对于 codemod 无法完全迁移代码的情况,请阅读 升级指南。我们还提供了一个 示例,演示如何将 Next.js 应用程序迁移到新的 API。

增强服务器操作的安全性

服务器操作 是可以在客户端调用的服务器端函数。它们通过在文件顶部添加 'use server' 指令并导出异步函数来定义。

即使服务器操作或实用程序函数在您的代码中没有其他地方导入,它仍然是一个公开可访问的 HTTP 端点。虽然这种行为在技术上是正确的,但它可能导致意外暴露此类函数。

为了提高安全性,我们引入了以下增强功能

  • 死代码消除:未使用的服务器操作不会将其 ID 暴露给客户端 JavaScript 包,从而减少包大小并提高性能。
  • 安全操作 ID:Next.js 现在创建不可猜测的、非确定性的 ID,以允许客户端引用和调用服务器操作。这些 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) {}

您仍然应该将服务器操作视为公共 HTTP 端点。了解有关 保护服务器操作 的更多信息。

静态路由指示器

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 等可观察性库深度集成 OpenTelemetry

此功能现已稳定,可以删除 experimental.instrumentationHook 配置选项。

此外,我们还与 Sentry 合作设计了一个新的 onRequestError 钩子,可用于

  • 捕获服务器上抛出的所有错误的重要上下文,包括
    • 路由器:页面路由器或应用程序路由器
    • 服务器上下文:服务器组件、服务器操作、路由处理程序或中间件
  • 将错误报告给您喜欢的可观察性提供程序。
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 函数 的更多信息。

开发和构建改进

服务器组件 HMR

在开发过程中,保存服务器组件时会重新执行它。这意味着,对您的 API 端点或第三方服务的任何 fetch 请求也会被调用。

为了提高本地开发性能并降低计费 API 调用的潜在成本,我们现在确保热模块替换 (HMR) 可以重用先前渲染的 fetch 响应。

了解有关 服务器组件 HMR 缓存 的更多信息。

应用路由的更快速静态生成

我们优化了静态生成,以提高构建速度,特别是对于网络请求缓慢的页面。

之前,我们的静态优化过程会渲染页面两次——一次是为了生成客户端导航的数据,第二次是为了渲染初始页面访问的 HTML。现在,我们重复使用第一次渲染,省略了第二次渲染过程,从而减少了工作量和构建时间。

此外,静态生成工作程序现在共享fetch缓存跨页面。如果一个fetch调用没有选择退出缓存,其结果会被同一工作程序处理的其他页面重用。这减少了对相同数据的请求次数。

高级静态生成控制(实验性)

我们添加了对更高级用例的实验性支持,这些用例需要对静态生成过程进行更多控制才能从中受益。

除非您有特殊需求,否则我们建议您坚持使用当前默认值,因为这些选项可能导致资源使用增加以及由于并发性增加而导致的潜在内存不足错误。

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周期。我们实施了两个改进

  1. 您现在可以在next.config中配置expireTime值。这以前是experimental.swrDelta选项。
  2. 将默认值更新为一年,确保大多数 CDN 可以完全按预期应用stale-while-revalidate语义。

我们也不再用我们的默认值覆盖自定义的Cache-Control值,允许完全控制并确保与任何 CDN 设置兼容。

最后,我们改进了自托管时的图像优化。以前,我们建议您安装sharp以在您的 Next.js 服务器上优化图像。此建议有时会被忽略。使用 Next.js 15,您不再需要手动安装sharp——Next.js 在使用next start或以独立输出模式运行时会自动使用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 用法的新规则。您可以在[email protected] 的变更日志中查看所有更改。

其他更改

  • RC 1博客文章中先前描述的所有更改
  • [重大变更] 我们已弃用在应用路由器中导出export const runtime = "experimental-edge"。用户现在应该切换到export const runtime = "edge"。我们添加了一个代码修改来执行此操作(PR)
  • [重大变更] 在渲染期间调用revalidateTagrevalidatePath现在将抛出错误(PR)
  • [重大变更] instrumentation.jsmiddleware.js文件现在将使用托管的 React 包(PR)
  • [重大变更] Node.js 的最低版本已更新到 18.18.0(PR)
  • [重大变更] next/dynamic:已弃用的suspense属性已被删除,当组件在应用路由器中使用时,它将不再插入空的 Suspense 边界(PR)
  • [重大变更] 在 Edge 运行时解析模块时,将不应用worker模块条件(PR)
  • [重大变更] 禁止在服务器组件中将ssr: false选项与next/dynamic一起使用(PR)
  • [改进] outputFileTracingRootoutputFileTracingIncludesoutputFileTracingExcludes已从实验性升级为稳定版(PR)
  • [改进] 避免将全局 CSS 文件与树中更深层的 CSS 模块文件合并(PR)
  • [改进] 可以通过NEXT_CACHE_HANDLER_PATH环境变量指定缓存处理程序(PR)
  • [改进] 页面路由器现在支持 React 18 和 React 19(PR)
  • [改进] 如果启用了 Inspector,错误覆盖层现在会显示一个按钮来复制 Node.js Inspector URL (PR)
  • [改进] App Router 上的客户端预取现在使用 priority 属性 (PR)
  • [改进] Next.js 现在提供了一个 unstable_rethrow 函数,用于在 App Router 中重新抛出 Next.js 内部错误 (PR)
  • [改进] unstable_after 现在可以在静态页面中使用 (PR)
  • [改进] 如果在 SSR 期间使用了 next/dynamic 组件,则会预取该块 (PR)
  • [改进] App Router 现在支持 esmExternals 选项 (PR)
  • [改进] experimental.allowDevelopmentBuild 选项可用于允许使用 NODE_ENV=developmentnext build 进行调试 (PR)
  • [改进] 页面路由器中现在禁用了服务器操作转换 (PR)
  • [改进] 构建 worker 现在会在退出时停止构建挂起 (PR)
  • [改进] 从服务器操作重定向时,重新验证现在将正确应用 (PR)
  • [改进] 边缘运行时上并行路由的动态参数现在得到正确处理 (PR)
  • [改进] 静态页面现在将在初始加载后尊重 staleTime (PR)
  • [改进] vercel/og 更新并修复了内存泄漏 (PR)
  • [改进] 更新了补丁时间,以允许使用 msw 等包进行 API 模拟 (PR)

贡献者

Next.js 是 3000 多位独立开发者以及我们在 Vercel 的核心团队共同努力的结果。此版本由以下人员提供支持

衷心感谢 @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 的帮助!