跳至内容
返回博客

2024年1月18日,星期四

Next.js 14.1

发布者

Next.js 14.1 包含了开发者体验改进,包括

立即升级或开始使用

终端
npx create-next-app@latest

改进的自托管

我们听到了您关于如何使用 Node.js 服务器、Docker 容器或静态导出自托管 Next.js 的改进清晰度的反馈。我们已经彻底修改了我们关于自托管的文档

使用 Next.js 14.1,我们还稳定了为增量静态再生和应用路由的更细粒度的 Data Cache 提供自定义缓存处理程序

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
};

在自托管时使用此配置非常重要,尤其是在使用 Kubernetes 等容器编排平台时,因为每个 Pod 都会拥有缓存的副本。使用自定义缓存处理器将允许您确保托管 Next.js 应用程序的所有 Pod 之间的一致性。

例如,您可以将缓存的值保存到任何地方,例如 Redis 或 Memcached。我们要感谢 @neshca 提供的 Redis 缓存处理器适配器 和示例。

Turbopack 改进

我们继续专注于本地 Next.js 开发的可靠性和性能

  • 可靠性:Turbopack 通过了整个 Next.js 开发测试套件,并用于 Vercel 的应用程序
  • 性能:改进 Turbopack 的初始编译时间和快速刷新时间
  • 内存使用:改进 Turbopack 的内存使用

我们计划在即将发布的版本中稳定 next dev --turbo,它仍然是可选的。

可靠性

使用 Turbopack 的 Next.js 现在通过了 **5600 个开发测试(94%)**,比上次更新增加了 600 个。您可以在 areweturboyet.com 上跟踪进度。

我们继续在所有 Vercel 的 Next.js 应用程序上使用 next dev --turbo,包括 vercel.comv0.dev。所有从事这些应用程序开发的工程师每天都在使用 Turbopack。

我们发现并修复了使用 Turbopack 的非常大的 Next.js 应用程序的一些问题。为了解决这些问题,我们在 Next.js 中现有的开发测试套件中添加了新的测试。

性能

对于大型 Next.js 应用程序 vercel.com,我们看到了

  • 本地服务器启动速度提高了 **76.7%**
  • 使用快速刷新更新代码的速度提高了 **96.3%**
  • 初始路由编译(不带缓存)速度提高了 **45.8%**(Turbopack 尚未实现磁盘缓存)

v0.dev 中,我们发现了一个优化 Turbopack 中发现和捆绑 React 客户端组件方式的机会,从而使初始编译时间 **最多提高了 61.5%**。在 vercel.com 中也观察到了这种性能改进。

未来的改进

Turbopack 目前具有内存缓存,可以提高快速刷新的增量编译时间。

但是,在重新启动 Next.js 开发服务器时,缓存当前不会保留。Turbopack 性能的下一个重要步骤是 **磁盘缓存**,这将允许在重新启动开发服务器时保留缓存。

开发者体验改进

改进的错误消息和快速刷新

我们知道清晰的错误信息对于您的本地开发体验至关重要。我们在运行next dev时,对改进堆栈跟踪和错误消息的质量进行了一些修复。

  • 以前显示捆绑程序错误(如webpack-internal)的错误现在会正确显示错误的源代码和受影响的文件。
  • 在客户端组件中看到错误并在编辑器中修复错误后,快速刷新功能不会清除错误屏幕,需要硬刷新才能解决。我们已经修复了许多此类问题。例如,尝试从客户端组件导出metadata

例如,这是一个之前的错误信息

An example of an error from a fetch call in Next.js 14.
Next.js 14 中 fetch 调用错误的一个示例。

Next.js 14.1 已将其改进为

Errors from fetch calls during rendering now display the source code of the error and the affected file.
渲染期间 fetch 调用的错误现在会显示错误的源代码和受影响的文件。

window.history.pushStatewindow.history.replaceState

App Router 现在允许使用原生pushStatereplaceState 方法来更新浏览器的历史记录栈,而无需重新加载页面。

pushStatereplaceState 调用集成到 Next.js App Router 中,允许您与usePathnameuseSearchParams 同步。

这在需要在保存状态(如筛选器、排序顺序或其他希望在重新加载时保留的信息)时立即更新 URL 时非常有用。

'use client';
 
import { useSearchParams } from 'next/navigation';
 
export default function SortProducts() {
  const searchParams = useSearchParams();
 
  function updateSorting(sortOrder: string) {
    const params = new URLSearchParams(searchParams.toString());
    params.set('sort', sortOrder);
    window.history.pushState(null, '', `?${params.toString()}`);
  }
 
  return (
    <>
      <button onClick={() => updateSorting('asc')}>Sort Ascending</button>
      <button onClick={() => updateSorting('desc')}>Sort Descending</button>
    </>
  );
}

详细了解如何将原生 History API 与 Next.js 配合使用。

数据缓存日志

为了提高在运行next dev时 Next.js 应用程序中缓存数据的可观察性,我们对logging配置选项进行了一些改进。

您现在可以显示是否存在缓存HITSKIP 以及请求的完整 URL。

终端
GET / 200 in 48ms
Compiled /fetch-cache in 117ms
 GET /fetch-cache 200 in 165ms
GET https://api.vercel.app/products/1 200 in 14ms (cache: HIT)
Compiled /fetch-no-store in 150ms
 GET /fetch-no-store 200 in 548ms
GET https://api.vercel.app/products/1 200 in 345ms (cache: SKIP)
  Cache missed reason: (cache: no-store)

可以通过next.config.js启用此功能。

next.config.js
module.exports = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
};

next/image 支持<picture> 和艺术指导

Next.js Image 组件现在通过getImageProps()(稳定版)支持更高级的用例,这些用例不需要直接使用<Image>。这包括

import { getImageProps } from 'next/image';
 
export default function Page() {
  const common = { alt: 'Hero', width: 800, height: 400 };
  const {
    props: { srcSet: dark },
  } = getImageProps({ ...common, src: '/dark.png' });
  const {
    props: { srcSet: light, ...rest },
  } = getImageProps({ ...common, src: '/light.png' });
 
  return (
    <picture>
      <source media="(prefers-color-scheme: dark)" srcSet={dark} />
      <source media="(prefers-color-scheme: light)" srcSet={light} />
      <img {...rest} />
    </picture>
  );
}

详细了解getImageProps()

并行和拦截路由

在 Next.js 14.1 中,我们对并行和拦截路由进行了**20 项改进**。

在过去的两个版本中,我们一直专注于提高 Next.js 的性能和可靠性。现在,我们已经能够根据您的反馈对并行拦截路由 进行许多改进。值得注意的是,我们添加了对通配符路由和服务器操作的支持。

  • 并行路由允许您在同一布局中同时或有条件地渲染一个或多个页面。对于应用程序中高度动态的部分(例如社交网站上的仪表板和 Feed),并行路由可用于实现复杂的路由模式。
  • 拦截路由允许您从应用程序的另一个部分加载路由到当前布局中。例如,当您在 Feed 中点击照片时,您可以将照片显示在模态窗口中,覆盖 Feed。在这种情况下,Next.js 会拦截/photo/123 路由,屏蔽 URL,并将其覆盖在/feed 上。

详细了解并行拦截路由查看示例

其他改进

14.0开始,我们修复了许多社区中获得高度评价的错误。

我们最近还发布了一些视频,解释缓存,以及一些App Router 的常见错误,您可能会觉得这些视频很有帮助。

  • [文档] 关于重定向 的新文档
  • [文档] 关于测试 的新文档
  • [文档] 包含生产检查清单 的新文档

  • [特性]<GoogleAnalytics /> 组件添加到 next/third-parties 中(文档
  • [改进] create-next-app 现在更小,安装速度更快(PR
  • [改进] 嵌套路由抛出的错误现在可以被 global-error 捕获(PR
  • [改进] redirect 现在在服务器操作中尊重 basePathPR
  • [改进] 修复了 App Router 中 next/scriptbeforeInteractive 的使用问题(PR
  • [改进] 自动转译 @aws-sdklodash 以加快路由启动速度(PR
  • [改进] 修复了使用 next devnext/font 时出现的未样式内容闪烁问题(PR
  • [改进]notFound 错误传播到段错误边界之外(PR
  • [改进] 修复了使用 Pages Router 国际化时从区域设置域名提供公共文件的问题(PR
  • [改进] 如果传递了无效的 revalidate 值,则会报错(PR
  • [改进] 修复了在 Linux 机器上构建在 Windows 上创建的构建时出现的路径问题(PR
  • [改进] 修复了在使用多区域应用和 basePath 时快速刷新/HMR 的问题(PR
  • [改进] 改进了从终止信号优雅关闭的过程(PR
  • [改进] 修复了模式路由在从不同路由拦截时发生的冲突问题(PR
  • [改进] 修复了在使用 basePath 配置时拦截路由的问题(PR
  • [改进] 当缺少的并行插槽导致 404 时显示警告(PR
  • [改进] 改进了在与通配符路由一起使用时拦截路由的方式(PR
  • [改进] 改进了在与 revalidatePath 一起使用时拦截路由的方式(PR
  • [改进] 修复了在并行路由中使用 @children 插槽的问题(PR
  • [改进] 修复了在并行路由中使用参数时出现的 TypeError 错误(PR
  • [改进] 修复了默认并行路由的通配符路由规范化问题(PR
  • [改进] 修复了 next build 摘要中并行路由的显示问题(PR
  • [改进] 修复了在使用拦截路由时的路由参数问题(PR
  • [改进] 改进了深度嵌套的并行/拦截路由(PR
  • [改进] 修复了拦截路由与路由组配对时出现的 404 问题(PR
  • [改进] 修复了并行路由与服务器操作/重新验证路由缓存的问题(PR
  • [改进] 修复了在拦截路由中使用 rewrites 的问题(PR
  • [改进] 服务器操作现在可以从第三方库中工作(PR
  • [改进] Next.js 现在可以用于 ESM 包中(PR

  • [改进] 针对 Material UI 等库的 Barrel 文件优化 (PR)
  • [改进] 构建过程现在会在不使用 Suspense 的情况下错误使用 useSearchParams 时失败 (PR)

贡献者

Next.js 是超过 3000 位独立开发者、Google 和 Meta 等行业合作伙伴以及 Vercel 核心团队共同努力的成果。加入社区,参与 GitHub 讨论RedditDiscord

此版本由以下人员贡献

以及以下人员的贡献:@OlehDutchenko、@eps1lon、@ebidel、@janicklas-ralph、@JohnPhamous、@chentsulin、@akawalsky、@BlankParticle、@dvoytenko、@smaeda-ks、@kenji-webdev、@rv-david、@icyJoseph、@dijonmusters、@A7med3bdulBaset、@jenewland1999、@mknichel、@kdy1、@housseindjirdeh、@max-programming、@redbmk、@SSakibHossain10、@jamesmillerburgess、@minaelee、@officialrajdeepsingh、@LorisSigrist、@yesl-kim、@StevenKamwaza、@manovotny、@mcexit、@remcohaszing、@ryo-manba、@TranquilMarmot、@vinaykulk621、@haritssr、@divquan、@IgorVaryvoda、@LukeSchlangen、@RiskyMH、@ash2048、@ManuWeb3、@msgadi、@dhayab、@ShahriarKh、@jvandenaardweg、@DestroyerXyz、@SwitchBladeAK、@ianmacartney、@justinh00k、@tiborsaas、@ArianHamdi、@li-jia-nan、@aramikuto、@jquinc30、@samcx、@Haosik、@AkifumiSato、@arnabsen、@nfroidure、@clbn、@siddtheone、@zbauman3、@anthonyshew、@alexfradiani、@CalebBarnes、@adk96r、@pacexy、@hichemfantar、@michaldudak、@redonkulus、@k-taro56、@mhughdo、@tknickman、@shumakmanohar、@vordgi、@hamirmahal、@gaspar09、@JCharante、@sjoerdvanBommel、@mass2527、@N-Ziermann、@tordans、@davidthorand、@rmathew8-gh、@chriskrogh、@shogunsea、@auipga、@SukkaW、@agustints、@OXXD、@clarencepenz、@better-salmon、@808vita、@coltonehrman、@tksst、@hugo-syn、@JakobJingleheimer、@Willem-Jaap、@brandonnorsworthy、@jaehunn、@jridgewell、@gtjamesa、@mugi-uno、@kentobento、@vivianyentran、@empflow、@samennis1、@mkcy3、@suhaotian、@imevanc、@d3lm、@amannn、@hallatore、@Dylan700、@mpsq、@mdio、@christianvuerings、@karlhorky、@simonhaenisch、@olci34、@zce、@LavaToaster、@rishabhpoddar、@jirihofman、@codercor、@devjiwonchoi、@JackieLi565、@thoushif、@pkellner、@jpfifer、@quisido、@tomfa、@raphaelbadia、@j9141997、@hongaar、@MadCcc、@luismulinari、@dumb-programmer、@nonoakij、@franky47、@robbertstevens、@bryndyment、@marcosmartini、@functino、@Anisi、@AdonisAgelis、@seangray-dev、@prkagrawal、@heloineto、@kn327、@ihommani、@MrNiceRicee、@falsepopsky、@thomasballinger、@tmilewski、@Vadman97、@dnhn、@RodrigoTomeES、@sadikkuzu、@gffuma、@Schniz、@joulev、@Athrun-Judah、@rasvanjaya21、@rashidul0405、@nguyenbry、@Mwimwii、@molebox、@mrr11k、@philwolstenholme、@IgorKowalczyk、@Zoe-Bot、@HanCiHu、@JackHowa、@goncy、@hirotomoyamada、@pveyes、@yeskunall、@ChendayUP、@hmaesta、@ajz003、@its-kunal、@joelhooks、@blurrah、@tariknh、@Vinlock、@Nayeem-XTREME、@aziyatali、@aspehler 和 @moka-ayumu。