跳到内容
返回博客

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 中,我们还稳定了为增量静态再生和 App Router 更细粒度的数据缓存提供自定义缓存处理程序的功能

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 现在通过了 5,600 个开发测试 (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 的性能和可靠性。现在,我们已经能够根据您的反馈,对 并行拦截路由 进行了许多改进。值得注意的是,我们添加了对全部捕获路由和服务器操作的支持。

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

了解更多关于 并行拦截路由查看示例

其他改进

14.0 以来,我们修复了社区中许多高票数的错误。

我们最近还发布了一些视频,解释了缓存 和一些您可能会觉得有用的 App Router 的常见错误

  • [文档] 关于 重定向 的新文档
  • [文档] 关于 测试 的新文档
  • [文档] 包含 生产环境清单 的新文档
  • [功能]next/third-parties 添加 <GoogleAnalytics /> 组件 (文档)
  • [改进] create-next-app 现在更小且安装速度更快 (PR)
  • [改进] 嵌套路由抛出错误时仍然可以被 global-error 捕获 (PR)
  • [改进] 在服务器操作中使用时,redirect 现在尊重 basePath (PR)
  • [改进] 修复 next/scriptbeforeInteractive 与 App Router 的使用 (PR)
  • [改进] 自动转译 @aws-sdklodash 以加快路由启动速度 (PR)
  • [改进] 修复 next devnext/font 导致的未样式化内容闪烁问题 (PR)
  • [改进]notFound 错误传播到段的错误边界之外 (PR)
  • [改进] 修复 Pages Router i18n 中从区域设置域提供公共文件的问题 (PR)
  • [改进] 如果传递了无效的 revalidate 值,则报错 (PR)
  • [改进] 修复在 Windows 上创建的构建在 linux 机器上的路径问题 (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)
  • [改进] 现在,如果错误地使用不带 SuspenseuseSearchParams,构建将会失败 (PR)

贡献者

Next.js 是超过 3,000 名独立开发者、谷歌和 Meta 等行业合作伙伴以及 Vercel 核心团队共同努力的成果。加入我们的社区:GitHub 讨论区, Reddit, and Discord.

此版本由以下团队为您带来

以及以下贡献者:@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。