2024年10月21日,星期一
Turbopack 开发模式现已稳定
作者漫漫长路,我们很高兴地宣布 next dev --turbo
现已稳定,并随时准备加速您的开发体验。我们一直在使用它来迭代 vercel.com、nextjs.org、v0以及我们所有其他应用程序,并取得了良好的成果。
自 8 年前发布以来,Next.js 已被用于构建各种应用,从周末的业余项目到复杂的企业级应用程序。Next.js 首次发布时,webpack 显然是该框架捆绑基础的最佳选择,但随着时间的推移,它在满足现代 Web 开发人员的需求方面遇到了挑战。我们的社区开始发现,在等待路由加载、代码更改反映以及生产构建部署时,迭代速度缓慢得令人痛苦。
我们投入了大量 时间 和 精力 来优化 webpack,但在某个时刻,我们感觉投入的精力并没有带来足够的改进。我们需要一个新的基础,它可以支持今天已经投入生产的众多 Next.js 应用程序,以及我们计划的未来创新,例如 React 服务器组件。
这些是我们对这个新打包器的要求
- 最少的重大更改
- 支持 App 路由器和 Pages 路由器
- 加快各种规模代码库的编译时间
- 开发构建与生产构建高度一致
- 高级生产优化(例如,模块内的树形抖动)
- 支持多个环境(如 Node.js 和浏览器)的模块图
- 维护人员和高级用户可以全面观察
我们评估了当时所有现有的解决方案,发现每个解决方案都存在与我们的需求和目标不符的权衡。因此,我们决定从头开始设计一个可以满足 Next.js 当下需求并掌控路线图的东西,以便我们能够构建和试验它在未来所需的功能。这就是我们创建 Turbopack 的动力。
我们首先优化了开发体验,而这正是我们今天发布的稳定版本。我们已使用 Vercel 的应用程序广泛地试用 Turbopack,并且显着提高了开发人员的迭代速度。例如,对于大型 Next.js 应用程序 vercel.com
,我们已经看到了
- 本地服务器启动速度提高了 76.7%。
- 使用快速刷新更新代码的速度提高了 96.3%。
- 在没有缓存的情况下,初始路由编译速度提高了 45.8%(Turbopack 尚未具备磁盘缓存功能)。
在这篇文章中,我们将讨论我们如何取得这些成果,以及其他一些亮点。我们还将明确说明此版本中可以期待的内容,并提供后续版本的路线图。
亮点
更快的路由初始编译
我们从社区听到的最大问题之一是,路由在开发过程中加载时间过长,这归结于 webpack 的编译速度。Next.js 会按需编译路由,以避免在需要之前编译所有可能的路由,从而使初始启动速度更快,内存使用量更低,但即使这样,您仍然可能会发现自己在等待单个页面加载时焦躁不安。
公平地说,像 webpack 这样的打包器在幕后做了很多事情。在首次编译路由时,打包器会从一个“入口点”开始。在 Next.js 的情况下,它是 page.tsx
和该路由的所有相关文件的组合,例如 layout.tsx
和 loading.tsx
等。解析这些入口点以查找 import
语句,这些语句会被解析为文件,然后这些文件会像入口点一样进行处理,此循环会持续进行,直到不再找到导入语句为止。此过程构建了一个模块图,该模块图不仅可以由 TypeScript/JavaScript 模块(包括 node_modules
)组成,还可以由 CSS 文件(全局 CSS 和 CSS 模块)以及静态文件(如导入的 next/image
图片)组成。
收集所有模块后,模块图用于创建 JavaScript 包,通常称为“块”。这些块是编译器的输出,在服务器端(在构建时或运行时)或浏览器中运行。
webpack 不支持创建生成多个环境输出的图,因此我们今天必须在 Next.js 中使用 webpack 运行至少两个单独的编译器,一个用于服务器,一个用于浏览器。我们必须首先编译服务器模块图,以便可以找到对 "use client"
的所有引用。构建服务器后,我们遍历其图以创建浏览器编译器的相关入口点。由于这是一个单独的 webpack 编译器,因此此过程中会产生一些开销,例如在客户端和服务器端重复解析相同的代码。
使用 Turbopack,我们着手消除运行多个编译器并在它们之间进行协调的开销。解决方案是使编译器能够感知多个不同的输出目标。在内部,这些被称为目标“转换”。我们可以将导入标记为从服务器到浏览器或从浏览器到服务器的转换。这使得 Turbopack 能够有效地捆绑服务器组件和客户端组件,以及从客户端组件导入的服务器函数。
除了提高性能外,使用单个编译器能够在一遍处理多个环境,还带来了可靠性和调试优势,因为我们不再需要在 Next.js 中的两个单独的编译器进程之间进行协调。
webpack 和 Turbopack 之间的另一个主要区别在于,Turbopack 可以跨多个 CPU 并行化工作,而使用 webpack 时,只有使用 SWC 的 TypeScript/JavaScript 转换步骤会被并行化。
Webpack 无法跨 CPU 并行化,因为为了有效地并行化,数据必须能够轻松地在线程之间访问。Webpack 的构建方式大量使用了大型 JavaScript 对象,这些对象在没有昂贵的序列化和反序列化的情况下难以跨线程共享。这种开销通常会抵消利用多个 CPU 带来的性能提升。Turbopack 使用 Rust 编写,没有同样的限制,并且从一开始就考虑了并行化。
我们还通过更快的文件系统读写、更快的模块解析以及跳过更多无副作用模块的工作来实现性能提升。
在 vercel.com
(一个大型 Next.js 应用程序)上使用 Turbopack 时,我们发现初始编译速度比使用 Webpack 的 Next.js 快了高达 45.8%。
更快的快速刷新
快速刷新是打包器用于将更改传播到您当前在浏览器中查看的路由的系统,有时也称为热模块替换 (HMR)。
Next.js 进行了更深入的集成,将快速刷新连接到 React,确保在您更改组件时 React 不会丢失状态。
使用 Webpack 时,我们发现当 JavaScript 模块数量达到一定数量时,快速刷新的性能会受到限制。Webpack 即使对于未更改的模块也需要进行图遍历并生成输出,这会随着 JavaScript 模块数量的增加线性扩展。
我们发现,当模块数量达到约 30,000 个时,代码更改始终至少需要 1 秒的开销来处理更新,无论更改大小如何。例如,更改 CSS 文件中的颜色可能需要 1 秒才能显示在屏幕上。
这种性能对于我们来说是不可接受的。我们认为增量构建应该只随着本地更改的大小而扩展,而不是随着路由或应用程序的大小而扩展。当 button.tsx
更改时,编译器只需要执行与该文件更改相关的操作,而不是重新计算不受更改影响的其他模块和输出文件。为了解决这个问题,我们在 Turbopack 中优先考虑了一个基础,该基础允许非常细粒度的重新计算工作。
这项工作变成了底层库,Turbo Engine,它使用自动按需驱动的增量计算架构,可以在几十毫秒内提供大型 Next.js 和 React 应用程序的交互式热重载。这种架构基于十多年的研究和先前技术,包括Webpack、Salsa、Parcel、Adapton和Rust 编译器的查询系统。
现在使用 Turbopack,快速刷新的速度会随着更改的大小而扩展,这就是我们能够在大型 Next.js 应用程序(如 vercel.com)上实现代码更新速度提升 96.3% 的原因。
高级跟踪
随着 Next.js 这些年来被越来越广泛地采用,我们发现越来越难以重现 GitHub 上报告的问题,特别是与编译器性能和内存使用相关的方面。这是因为大多数人无法共享其应用程序代码,或者当他们共享代码时,应用程序无法运行,因为它需要数据库或其他设置。
为了解决这个问题,我们向 Next.js 的内部添加了跟踪功能。这些跟踪信息写入 .next
文件夹中的一个文件中,并且不包含应用程序代码,只包含文件路径、编译器在其上花费的时间以及其他时间信息,例如各个转换。但是,使用 Webpack 时,我们从未找到一种好的方法来清楚地区分编译器的内存使用情况与框架或应用程序代码的内存使用情况,因为它们都在同一个 Node.js 实例中运行。
使用 Turbopack,我们能够从一开始就进行仪器设计。我们在Turbo Engine中实现了一个仪器层,允许收集每个单独函数的时间信息。我们能够扩展这些跟踪信息,以便跟踪每个函数的内存分配、释放和持久化内存。
这种新的高级跟踪为我们提供了调查速度下降和内存使用情况所需的所有信息;它只需要跟踪信息,而不是完整的代码库。
为了处理这些新的跟踪信息,我们实现了一个自定义跟踪查看器,无论应用程序和跟踪信息的大小如何,都能保持良好的性能。它是一个专门为调查 Turbopack 的速度下降和内存使用情况而构建的跟踪查看器,并且由于它缩短了反馈循环,因此能够帮助我们优化了许多早期采用者应用程序的性能。
虽然跟踪查看器最初是为内部使用而构建的(并且它适用于需要深入技术分析的情况),但我们已经实现了在 Next.js 中自行运行它所需的组件。您可以使用这些说明生成 Turbopack 跟踪信息。然后,当跟踪信息生成后,您可以使用 next internal turbo-trace-server .next/trace-turbopack
启动服务器,以便检查跟踪信息。这里有一个关于跟踪查看器的简短视频概述可用在此处。
编译时间更稳定
使用 Webpack 的 Next.js 时,编译时间通常不够透明。在一个案例中,打开一个页面可能需要 10 秒,而在另一个案例中,可能需要 20 秒。虽然缓存可能存在,但有时它产生的影响不足以产生一致的结果。即使在没有缓存的编译中,我们也发现存在一些差异。
Turbopack 的底层架构确保了编译时间差异更加一致。路由的编译时间仅变化几个百分点,这使我们能够持续优化编译器性能。
开发构建与生产构建更加一致
为了使用 Webpack 优化编译速度,我们不得不接受一些会导致开发环境和生产环境出现差异的权衡。这些权衡的一些示例是,我们使用 style-loader
,它将样式注入到页面中并允许快速刷新它们,而无需重新加载页面。但是,这意味着样式是在开发中通过 JavaScript 注入的,这会导致出现未设置样式内容的闪烁。我们解决了未设置样式内容的闪烁问题,因此您不会看到它。另一个示例是,使用 Webpack 的 Next.js 使用 eval-source-map
,这意味着所有代码都包装在 eval
中,并且源映射包含在其中,这确保了开发中源映射可用,但代价是捆绑后的代码更难以检查和调试。虽然 Webpack 支持使用 source-map
选项输出完整的源映射,但这会对编译时间和内存使用造成过大的影响。
对于 Turbopack,我们一开始就致力于默认解决这些问题,在不使用eval
的情况下输出 CSS 文件和源映射。Turbopack 利用了sections
源映射,这是源映射规范中一个相对较新的部分,它允许更有效地合并源映射输出。以前我们必须在一个地方生成所有映射,现在我们可以更细粒度地生成和缓存它们。
Turbopack 中的 CSS 处理始终输出 CSS 文件,并且类似于 JavaScript 处理,它可以通过 Turbopack 开发运行时的一部分机制来更新 CSS 文件,而无需刷新浏览器。
现在我们可以自信地说,如果某些功能在使用 Turbopack 的开发环境中正常工作,那么它在生产环境中也能正常工作并表现相同。
我们的第一个稳定版本
两年前,我们在 Next.js 13 中引入了 Turbopack 作为 alpha 版本,提供了其性能潜力的预览。虽然最初的结果很有希望,但它只支持基本用法——许多 Next.js 功能,如basePath
,尚未实现。
在接下来的一年里,我们专注于添加缺失的 Next.js 和打包功能。根据社区反馈,我们决定完全专注于next dev
体验,以便我们可以解决最常见的迭代速度问题。到去年的 Next.js Conf,90% 的开发测试都已通过,Vercel 开发人员已经在日常开发中使用 Turbopack 了。
在 4 月份,我们宣布了 Next.js 14.2,其测试通过率达到 99.8%,并在不久之后达到 100%。从那时起,我们解决了 GitHub 上报告的问题,尤其是在 npm 包、Fast Refresh 和错误位置准确性方面。
诚然,通往稳定的道路花了很长时间,但这主要归因于 Next.js 广泛的测试套件,它为稳定性设定了很高的标准。我们已经花了 8 年时间来发现边缘情况并添加了 6599 个开发测试,这些测试也需要通过 Turbopack。另一个因素是我们设计的 Turbopack 具有与 webpack 完全不同的架构。简单地将 webpack 移植到 Rust 会更容易,但不会实现我们想要达到的性能提升。
现在 Turbopack 通过了所有测试,并已通过顶级 npm 包的验证,并且解决了早期采用者的反馈,我们准备将其标记为稳定版本。
稳定到底意味着什么?
这在过去一直是一个令人困惑的点,因此我们将利用本节来澄清此版本为 Next.js 社区解锁了什么。
此版本特别将next dev --turbo
命令标记为稳定版本。生产构建(next build --turbo
)尚不支持,但请继续阅读以获取更新,因为它们正在开发中。我们最终计划在 Next.js 之外发布 Turbopack 的独立版本,但我们希望首先通过增强 Next.js 社区的体验来证明其价值。
除了我们在下一节中将介绍的不支持的功能外,Turbopack 应该与 Next.js 的所有稳定功能一起使用。为清楚起见,Turbopack 支持 App Router 和 Pages Router。实验性功能可能支持也可能不支持 Turbopack,但它们肯定会在被标记为稳定时得到支持。
如果您的应用程序具有 webpack 自定义,但仅添加了 webpack 加载器,则您可能可以通过为 Turbopack 配置加载器来使用 Turbopack。您可以阅读文档了解 Turbopack 中的 webpack 加载器支持。
以下是经过验证可与 Turbopack 一起使用的 webpack 加载器列表
@svgr/webpack
babel-loader
url-loader
file-loader
raw-loader
tsconfig-paths-webpack-plugin
— 开箱即用,无需插件。- 大多数其他加载器也适用,因为我们支持 webpack 加载器 API 的一部分。
大多数 CSS 和 CSS-in-JS 库都受支持
- 受支持
- Tailwind CSS
- @emotion/react
- Sass
- styled-components
- Bootstrap
- Antd
- node-sass
- JSS
- Emotion
- theme-ui (使用 Emotion)
- @chakra-ui/core (使用 Emotion)
- aphrodite
- 当前不受支持
- Less — 您可以添加 less-loader。Next.js 与 webpack 也不开箱即用地支持 Less。
- @vanilla-extract/css — 使用自定义 webpack 插件 — 我们将在未来研究支持所需 hook 的方法。
- StyleX — 需要 Babel 转换和对
data:
属性的支持 — 我们将在next build --turbo
稳定后研究支持 StyleX 的方法。
性能
我们要指出,今天发布的版本的性能明显优于 webpack,但这不是最终的性能指标。我们一直在遵循 Kent Beck 的著名公式“使其工作。使其良好。使其快速”。到目前为止,我们的大部分工作都投入到了“使其工作”阶段,因为我们必须赶上 Next.js 和 webpack 的范围,它们已经发展了近十年。
Turbopack 大力押注其缓存基础设施,但正如您所知,缓存是软件开发中仅有的两件难事之一。根据经验,我们知道在没有明确为其构建的架构中添加缓存会导致不良结果,因此我们即使对最细粒度的函数也启用了缓存。这意味着重建速度非常快,但代价是冷启动和内存使用量增加,我们正在努力实现更好的平衡。有趣的是,我们可以使用我们在文章前面提到的高级跟踪来查找低效之处并分析哪些函数最值得缓存。
在过去的 3 个月里,我们已经取得了一些重大改进。比较Next.js 15 RC 2 中的 Turbopack 与15 RC 1 中的 Turbopack 可以看出这些优化的结果
- **内存**使用量平均减少 25-35%。
- 对于包含数千个模块的大页面,**初始编译**速度提高了 30-50%。
Turbopack 的稳定版本包含一个内存缓存,必须在每次重新启动开发服务器时重建,对于大型应用程序,这可能需要十秒钟或更长时间。我们非常兴奋的一件事是我们正在测试磁盘持久化缓存时看到的巨大优势,我们将在本文后面介绍。
重大更改
构建我们自己的打包器的巨大动力是需要尽可能地匹配 webpack 的现有行为,这是我们当时无法用任何现有解决方案保证的。这包括文件解析方式以及 webpack 的较小功能,例如一些 npm 包使用的webpackIgnore
注释。
不幸的是,我们确实不得不删除一些功能才能使 Turbopack 和相关的 Next.js 实现面向未来。当您使用 webpack 时,这些功能仍将得到支持。
以下是一些亮点,让我们深入了解我们必须更改它们的原因
不支持webpack()
配置。Turbopack 不是 webpack,它没有相同的配置选项结构,尽管它确实支持许多相同的功能。具体来说,我们实现了对webpack 加载器和解析别名的支持。大多数转换代码的 webpack 加载器都开箱即用。某些执行特殊操作的 webpack 加载器,例如 webpack 子编译器和发出文件,不受支持。
.babelrc
不会自动转换代码。Turbopack 默认情况下利用SWC。您仍然可以根据需要添加babel-loader
,但我们确保默认值始终很快,并且这些值在架构方面也合理。我们必须始终运行 SWC,即使您配置了.babelrc
,以便处理其他优化。这类似于 webpack 始终必须运行acorn
解析器以进行进一步优化。如果您在 Turbopack 中使用 SWC 而不是 Babel,我们可以解析一次并在整个 Turbopack 中端到端利用相同的抽象语法树 (AST)。
一些不太常用的 CSS Modules 功能。我们已将 CSS 处理从 PostCSS 切换到Lightning CSS。Lightning CSS 是一个速度明显更快的 CSS 编译器,开箱即用地支持 CSS 转换、缩小和 CSS Modules。权衡是某些不太常用的功能不受支持。具体来说,:global
和:local
伪选择器(它们的函数变体:global()
和:local()
仍然有效)、@value
以及:import / :export
ICSS 规则。它也比其他 CSS 解析器严格一些,并且会指出代码中的错误而不是忽略它们。
在添加 Lightning CSS 的过程中,我们也回馈了该项目。例如,我们为 CSS Modules 实现了更细粒度的选项,可以禁用 CSS 网格前缀以及 CSS Modules 的pure
模式。这使得从 webpack 中的 css-loader 迁移到 Lightning CSS 变得更加容易。我们还改进了对不支持的 CSS Modules 功能的错误提示。
我们感谢 Lightning CSS 的作者兼维护者 Devon Govett,感谢他持续与我们合作。
实验性功能。由于我们专注于 Turbopack 在 Next.js 中的稳定性,因此我们决定首先专注于 Next.js 中可用的稳定功能。
有关完整列表,请参阅 文档页面。
路线图
Turbopack 已经取得了长足的进步,但仍有很多工作要做。未来即将推出的两个令人兴奋的功能是持久缓存和生产构建。我们预计推出顺序如下
- 持久缓存 — 未来次要版本
- 构建 Beta 版 — 未来次要版本
- 构建候选版本 — 未来次要版本
- 构建稳定版 — 未来次要版本
- 在 create-next-app 中推荐用于新应用程序 — 未来次要版本
- 在您没有自定义 webpack 配置的情况下,成为 Next.js 的默认设置 — 未来主要版本
虽然 webpack 将保留在 Next.js 中,但我们预计由于 Turbopack 的优势,大多数 Next.js 应用程序将希望使用它。一旦 Turbopack 的生产构建完成,我们将开始着手支持常用的 webpack 插件。
我们对 Turbopack 的未来计划比较宽泛,但我们希望将本文内容限制在我们可以在可预见的未来自信地发布的内容。我们可能只讨论两个功能,但其中包含很多工作,因此值得深入探讨。
持久缓存(重启后的快速刷新)
持久缓存意味着以一种允许在开发服务器重启或跨多个生产构建中重复使用的方式存储编译器完成的工作。
简而言之,Turbopack 避免重复执行相同的工作,即使您重新启动也是如此。
如“更快的快速刷新”部分所述,我们构建了 Turbo Engine 以确保工作可以并行化和缓存,以便每当您更改文件时,我们只需要运行与该文件更改相关的工作。如果我们可以在重启和打开路由时提供这种体验会怎么样?我们不必重做先前开发会话中已经完成的编译工作。如果我们可以获得快速刷新的好处,但用于打开先前开发会话中编译的路由以及使用next build
的多个构建中呢?
这正是我们一直在努力的方向:一个用于 Turbo Engine 的新存储层,它支持将编译工作持久化到磁盘并在启动开发服务器或再次构建时恢复它。
虽然 webpack 在 Next.js 中默认启用了磁盘缓存,但它有一些限制。值得注意的是,缓存的大部分内容必须从磁盘恢复并读入内存才能正常工作。感觉缓存的粒度不够细。例如,在 Vercel 的大型应用程序中,我们发现当缓存增长到足够大时,webpack 磁盘缓存甚至比从头开始完成所有工作还要慢。
与使用 webpack 的现有磁盘缓存不同,Turbopack 的持久缓存确实感觉像是重启后的快速刷新。第一次编译需要超过 10 秒的路由,一旦编译完成,从缓存中恢复只需不到 500 毫秒。
我们在使用 Turbopack 的next build
中也看到了类似的结果,其中仅重新编译已更改的文件,其他所有内容都保持不变。在next build
执行的多个步骤中,这将大部分时间从运行编译和捆绑转移到运行 TypeScript 类型检查。
持久缓存目前正在开发中,因为我们希望首先使用我们内部的 Next.js 应用程序对其进行验证。初步结果非常有希望,并且随着我们不断优化这些热点路径,性能将进一步提高。
一旦持久缓存稳定,它将默认启用。启用持久缓存不需要更改您的代码库。
如果您有兴趣测试持久缓存,请联系我们!
生产构建
我们很高兴地分享,我们在使用 Turbopack 实现稳定的生产构建方面取得了重大进展。目前,我们 96% 的生产测试已通过,这是一个巨大的进步。但是,在我们可以自信地推荐 Turbopack 用于大规模生产之前,仍然有一些领域需要更多工作。
与开发相比,生产构建带来了自身独特的挑战,我们正在积极努力解决这些挑战。下面,我们将介绍哪些内容已经过优化以及哪些内容仍在进行中。
生产优化
正确性
确保正确性对于可靠的生产构建至关重要。以下是当前状态
- CSS 分块:正在进行中。此功能对于将 CSS 分割成更小的块至关重要,它只允许应用程序的每个部分加载必要的 CSS,这有助于减少加载时间并确保 CSS 规则的正确排序。
- 生产环境 JS 运行时:已完成。这确保了 JavaScript 运行时在生产环境中按预期运行,提供可靠性和稳定性。
- 基于内容的文件名哈希:尚未实现。基于内容的哈希将允许我们根据内容生成文件名,从而在浏览器中实现更有效的长期缓存。
UX 性能优化
UX 性能是提供快速加载时间和高效资源利用的关键。以下是我们正在努力的方向
- JS 压缩:已完成。我们已实现 SWC 压缩,自 Next.js 13 以来,Next.js 已经在 webpack 中使用了它。
- CSS 压缩:已完成。使用 Lightning CSS 进行 CSS 压缩,这对于减小样式表的大小非常重要。
- 全局信息(整个应用程序优化):已完成。Turbopack 可以应用需要应用程序中所有路由数据的优化,例如模块 ID 哈希。
- 摇树优化:部分完成。正在进行中。我们部分支持摇树优化,这有助于消除未使用的代码并减小捆绑包大小。但是,在某些情况下,摇树优化尚未完全有效
- 动态导入:对于使用
next/dynamic
之类的动态导入,摇树优化是有限的。 - 复杂的导出:某些类型的导出,例如
export { foo as "string name" }
。 - 非 ES 模块:CommonJS 模块无法进行摇树优化。
- 桶文件:来自桶文件的重新导出效率低下,在跳过无副作用的模块方面存在限制。
- 碎片化:在某些情况下,摇树优化可能会创建过多碎片,导致捆绑包效率低下。
- 动态导入:对于使用
- 模块 ID 哈希(部分):正在进行中。模块 ID 哈希已部分实现,但我们正在努力提高性能。完全启用后,它将有助于减小最终捆绑包的大小。
- 导出名称混淆:正在进行中。这涉及减少导出名称的大小以减小最终捆绑包的大小。
- 作用域提升:尚未实现。作用域提升将有助于通过将较小的 JavaScript 模块合并到单个作用域中来减小捆绑包大小,从而减少开销并提高性能。
- 生产环境优化的 JS 分块:尚未实现。将 JavaScript 分块以最大程度地减少重复对于提高加载性能至关重要,尤其是在大型应用程序中。
敬请期待
我们很高兴能够自信地推荐next dev --turbo
,我们迫不及待地想听听它如何改善您的开发体验。今天就尝试一下,亲身体验性能提升。
这仅仅是个开始——持久缓存和生产构建即将到来,这将为您的工作流程带来更快的速度和更高的可靠性。
随着我们不断努力确保正确性和优化性能以无缝处理甚至最大的应用程序,我们将分享更多更新。敬请关注未来的版本和改进,我们将努力使 Turbopack 成为开发和生产构建的最佳解决方案。
贡献者
我们感谢成千上万的开发人员在 Turbopack 测试版和候选发布阶段参与测试、报告问题和验证修复。
此版本由以下人员提供