跳到内容
返回博客

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(自动化代码转换),以帮助自动化升级重大更改。

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

npx @next/codemod@canary upgrade rc

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

了解更多关于Next.js codemods的信息。

用于开发的Turbopack

Turbopack用于本地开发将在Next.js 15的正式发布中变得稳定,同时仍然是可选的。您现在可以通过运行以下命令来尝试它

next dev --turbo

感谢数千名开发者在Turbopack Beta和发布候选阶段参与测试、报告问题和验证修复,我们已经解决了54个GitHub问题,自Next.js 15第一个发布候选版本以来。除了社区的努力,我们在vercel.comv0.appnextjs.org上的内部测试也发现了许多额外的改进。

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

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

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

展望未来,Turbopack团队在持久缓存、内存使用量减少和next build的Turbopack方面取得了重大进展——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
  • layout.jspage.jsroute.jsdefault.jsgenerateMetadatagenerateViewport中的params
  • page.js中的searchParams

为了便于迁移,这些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等可观察性库。

此功能现在稳定,并且可以删除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缓存的信息。

App Router的更快静态生成

我们优化了静态生成以缩短构建时间,特别是对于网络请求较慢的页面。

以前,我们的静态优化过程会渲染页面两次——一次是为了生成客户端导航的数据,第二次是为了渲染初始页面访问的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设置兼容。

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

其他更改

  • RC 1 博客文章中先前描述的所有更改
  • [重大更改] 我们已弃用在App Router中导出export const runtime = "experimental-edge"。用户现在应切换到export const runtime = "edge"。我们添加了一个codemod来执行此操作(PR
  • [重大更改] 在渲染期间调用revalidateTagrevalidatePath现在会抛出错误(PR
  • [重大更改] instrumentation.jsmiddleware.js文件现在将使用供应商的React包(PR
  • [重大更改] 最低要求的Node.js版本已更新为18.18.0(PR
  • [重大更改] next/dynamic:已删除已弃用的suspense prop,当组件在App Router中使用时,它不再插入空的Suspense边界(PR
  • [重大更改] 在Edge Runtime上解析模块时,将不应用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
  • [改进] esmExternals选项现在在App Router上受支持(PR
  • [改进] experimental.allowDevelopmentBuild选项可用于允许NODE_ENV=developmentnext build一起用于调试目的(PR
  • [改进] 服务器操作转换现在在页面路由器中禁用(PR
  • [改进] 构建工作者现在将在退出时阻止构建挂起(PR
  • [改进] 从服务器操作重定向时,重新验证现在将正确应用(PR
  • [改进] 在Edge Runtime上,动态参数现在可以正确处理并行路由(PR
  • [改进] 静态页面现在将在初始加载后遵循staleTime(PR
  • [改进] vercel/og已更新并修复了内存泄漏(PR
  • [改进] 补丁时间已更新,允许使用msw等包进行API模拟(PR

贡献者

Next.js是3,000多位独立开发者和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的帮助!