跳到内容

Rolldown 集成

Vite 计划集成 Rolldown,这是一个由 Rust 驱动的 JavaScript 打包器,旨在提高构建性能和能力。

什么是 Rolldown?

Rolldown 是一个现代、高性能的 JavaScript 打包器,用 Rust 编写。它被设计为 Rollup 的直接替代品,旨在提供显著的性能改进,同时保持与现有生态系统的兼容性。

Rolldown 专注于三个关键原则

  • 速度:使用 Rust 构建,以实现最佳性能
  • 兼容性:与现有的 Rollup 插件配合使用
  • 优化:具有超越 esbuild 和 Rollup 实现的功能

Vite 为什么要迁移到 Rolldown

  1. 统一:Vite 目前使用 esbuild 进行依赖预构建,使用 Rollup 进行生产环境构建。Rolldown 旨在将这些统一到一个高性能的打包器中,可以用于两种目的,从而降低复杂性。

  2. 性能:Rolldown 基于 Rust 的实现提供了比基于 JavaScript 的打包器显著的性能改进。虽然具体的基准测试可能会因项目规模和复杂性而异,但早期测试表明,与 Rollup 相比,速度提升很有希望。

  3. 附加功能:Rolldown 引入了 Rollup 或 esbuild 中没有的功能,例如高级代码块分割控制、内置 HMR 和模块联邦。

有关 Rolldown 背后的动机的更多见解,请参阅构建 Rolldown 的原因

尝试 rolldown-vite 的好处

  • 体验显著更快的构建时间,尤其是对于大型项目
  • 提供有价值的反馈,以帮助塑造 Vite 打包体验的未来
  • 为最终的官方 Rolldown 集成做好项目准备

如何尝试 Rolldown

Vite 的 rolldown 驱动版本目前作为一个单独的包 rolldown-vite 提供。如果您的项目直接依赖于 vite,则可以在项目的 package.json 中将 vite 包别名为 rolldown-vite,这将导致直接替换。

json
{
  "dependencies": {
    "vite": "^6.0.0"
    "vite": "npm:rolldown-vite@latest"
  }
}

如果您使用 Vitepress 或将 Vite 作为对等依赖的元框架,则必须覆盖 package.json 中的 vite 依赖项,这会因您的包管理器而略有不同

json
{
  "overrides": {
    "vite": "npm:rolldown-vite@latest"
  }
}
json
{
  "resolutions": {
    "vite": "npm:rolldown-vite@latest"
  }
}
json
{
  "pnpm": {
    "overrides": {
      "vite": "npm:rolldown-vite@latest"
    }
  }
}
json
{
  "overrides": {
    "vite": "npm:rolldown-vite@latest"
  }
}

添加这些覆盖后,重新安装您的依赖项,并像往常一样启动您的开发服务器或构建您的项目。无需进一步的配置更改。

已知限制

虽然 Rolldown 旨在成为 Rollup 的直接替代品,但仍有一些功能正在实施中,并且存在细微的有意行为差异。有关完整列表,请参阅此 GitHub PR,它会定期更新。

选项验证警告

当传递未知或无效选项时,Rolldown 会输出警告。由于 Rolldown 不支持 Rollup 中提供的一些选项,因此您可能会遇到基于您或您使用的元框架设置的选项的警告。下面,您可以找到此类警告消息的示例

Warning validate output options.

  • For the "generatedCode". Invalid key: Expected never but received "generatedCode".

如果您自己没有传递该选项,则必须由使用的框架修复此问题。

API 差异

manualChunksadvancedChunks

Rolldown 不支持 Rollup 中可用的 manualChunks 选项。相反,它通过 advancedChunks 选项提供更精细的设置,该选项更类似于 webpack 的 splitChunk

js
// Old configuration (Rollup)
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (/\/react(?:-dom)?/.test(id)) {
            return 'vendor'
          }
        }
      }
    }
  }
}

// New configuration (Rolldown)
export default {
  build: {
    rollupOptions: {
      output: {
        advancedChunks: {
          groups: [{ name: 'vendor', test: /\/react(?:-dom)?// }]
        }
      }
    }
  }
}

性能

rolldown-vite 专注于确保与现有生态系统的兼容性,因此默认设置旨在实现平稳过渡。您可以通过切换到更快的基于 Rust 的内部插件和其他自定义设置来获得进一步的性能提升。

启用原生插件

由于 Rolldown 和 Oxc,各种内部 Vite 插件(例如别名或解析插件)已转换为 Rust。在撰写本文时,默认情况下未启用使用这些插件,因为它们的行为可能与 JavaScript 版本不同。

要测试它们,您可以在 Vite 配置中将 experimental.enableNativePlugin 选项设置为 true

@vitejs/plugin-react-oxc

当使用 @vitejs/plugin-react@vitejs/plugin-react-swc 时,您可以切换到 @vitejs/plugin-react-oxc 插件,该插件使用 Oxc 进行 React 的快速刷新,而不是 Babel 或 SWC。它被设计为直接替换,提供更好的构建性能并与 rolldown-vite 的底层架构保持一致。

请注意,如果您没有使用任何 Babel 或 SWC 插件(包括 React 编译器),或者改变 SWC 选项,则只能切换到 @vitejs/plugin-react-oxc

withFilter 包装器

插件作者可以选择使用 hook filter 功能来减少 Rust 和 JavaScript 运行时之间的通信开销。但是,如果某些使用的插件尚未(还)使用此功能,但您仍然想从中受益,则可以使用 withFilter 包装器来自己用过滤器包装插件。

js
// In your vite.config.ts
import { withFilter, defineConfig } from 'vite'
import svgr from 'vite-plugin-svgr'

export default defineConfig({
  plugins: [
    // Load the `svgr` plugin only for files which end in `.svg?react`
    withFilter(
      svgr({
        /*...*/
      }),
      { load: { id: /\.svg\?react$/ } },
    ),
  ],
})

报告问题

由于这是一个实验性集成,您可能会遇到问题。如果遇到问题,请在 vitejs/rolldown-vite 存储库中报告它们,而不是在主 Vite 存储库中

报告问题时,请遵循适当的问题模板并提供其中要求的内容,通常包括

  • 该问题的最小重现
  • 您的环境详细信息(操作系统、Node 版本、包管理器)
  • 任何相关的错误消息或日志

对于实时讨论和问题排查,请务必加入 Rolldown Discord

版本控制策略

rolldown-vite 的版本控制策略使其主版本和次版本与普通 Vite 包的版本一致。这种同步确保了特定普通 Vite 次版本中存在的功能也包含在相应的 rolldown-vite 次版本中。但是,重要的是要注意,补丁版本在两个项目之间不同步。如果您想知道普通 Vite 中的特定更改是否已包含在 rolldown-vite 中,您可以随时查看 rolldown-vite 的单独更新日志进行确认。

此外,请注意 rolldown-vite 本身被认为是实验性的。由于其实验性质,即使在其补丁版本中也可能会引入重大更改。此外,请注意 rolldown-vite 仅接收其最新次版本的更新。即使对于重要的安全或错误修复,也不会为较旧的主版本或次版本创建补丁。

未来计划

rolldown-vite 包是一个临时解决方案,用于收集反馈并稳定 Rolldown 集成。将来,此功能将合并回主 Vite 存储库。

我们鼓励您试用 rolldown-vite,并通过反馈和问题报告为其开发做出贡献。

将来,我们还将为 Vite 引入“完整捆绑模式”,该模式将在生产环境和开发模式中提供捆绑文件。

为什么要引入完整捆绑模式?

Vite 以其非捆绑开发服务器方法而闻名,这是 Vite 在首次引入时速度和受欢迎程度的主要原因。这种方法最初是一项实验,目的是看看在没有传统捆绑的情况下,我们可以在多大程度上提高开发服务器的性能。

但是,随着项目规模和复杂性的增加,出现了两个主要挑战

  1. 开发/生产不一致:在开发中提供的非捆绑 JavaScript 与捆绑的生产版本之间创建了不同的运行时行为。这可能会导致仅在生产环境中显现的问题,从而使调试更加困难。

  2. 开发期间的性能下降:非捆绑方法导致每个模块被单独获取,这会产生大量的网络请求。虽然这对生产环境没有影响,但它会在开发服务器启动期间以及刷新开发页面时造成大量的开销。这种影响在必须处理数百甚至数千个单独请求的大型应用程序中尤其明显。当开发人员使用网络代理时,这些瓶颈变得更加严重,导致刷新时间变慢并降低了开发人员体验。

通过 Rolldown 集成,我们有机会统一开发和生产体验,同时保持 Vite 的标志性性能。完整捆绑模式不仅允许在生产环境中,而且在开发过程中提供捆绑文件,从而结合了两全其美的优势

  • 即使对于大型应用程序,启动时间也很快
  • 开发和生产之间的行为一致
  • 减少页面刷新时的网络开销
  • 在 ESM 输出之上保持高效的 HMR

当引入完整捆绑模式时,它最初将是一个选择加入功能。与 Rolldown 集成类似,我们的目标是在收集反馈并确保稳定性后使其成为默认设置。

插件/框架作者指南

提示

本节主要与插件和框架作者相关。如果您是用户,则可以跳过本节。

主要变更概述

  • Rolldown 用于构建(之前使用 Rollup)
  • Rolldown 用于优化器(之前使用 esbuild)
  • CommonJS 支持由 Rolldown 处理(之前使用 @rollup/plugin-commonjs)
  • Oxc 用于语法降低(之前使用 esbuild)
  • Lightning CSS 默认用于 CSS 压缩(之前使用 esbuild)
  • Oxc 压缩器默认用于 JS 压缩(之前使用 esbuild)
  • Rolldown 用于捆绑配置(之前使用 esbuild)

检测 rolldown-vite

警告

在大多数情况下,您不需要检测您的插件是否在 rolldown-vitevite 上运行,您应该力求在两者之间保持一致的行为,而无需条件分支。

如果您在使用 rolldown-vite 时需要不同的行为,您有两种方法可以检测是否使用了 rolldown-vite

检查 this.meta.rolldownVersion 是否存在

js
const plugin = {
  resolveId() {
    if (this.meta.rolldownVersion) {
      // logic for rolldown-vite
    } else {
      // logic for rollup-vite
    }
  },
}

提示

自 Vite 7.0.0 起,this.meta 在所有钩子中都可用。在以前的版本中,this.meta 在 Vite 特定的钩子(例如 config 钩子)中不可用。


检查 rolldownVersion 导出是否存在

js
import * as vite from 'vite'

if (vite.rolldownVersion) {
  // logic for rolldown-vite
} else {
  // logic for rollup-vite
}

如果您将 vite 作为依赖项(而不是对等依赖项),则 rolldownVersion 导出非常有用,因为它可以在代码中的任何位置使用。

忽略 Rolldown 中的选项验证

上面提到,当传递未知或无效选项时,Rolldown 会输出警告。

可以通过检查是否使用 rolldown-vite 运行来有条件地传递选项来修复此问题,如上面所示

transformWithEsbuild 需要单独安装 esbuild

由于 Vite 本身不再使用 esbuild,因此 esbuild 现在是一个可选的对等依赖项。如果您的插件使用 transformWithEsbuild,则该插件需要将 esbuild 添加到其依赖项中,或者用户需要手动安装它。

建议的迁移是使用新导出的 transformWithOxc 函数,该函数利用 Oxc 而不是 esbuild

esbuild 选项的兼容性层

Rolldown-Vite 有一个兼容性层,用于将 esbuild 的选项转换为相应的 Oxc 或 rolldown 选项。正如在ecosystem-ci中测试的那样,这在许多情况下都有效,包括简单的 esbuild 插件。也就是说,我们将来会删除 esbuild 选项支持,并鼓励您尝试相应的 Oxc 或 rolldown 选项。您可以从 configResolved 钩子中获取由兼容性层设置的选项。

js
const plugin = {
  name: 'log-config',
  configResolved(config) {
    console.log('options', config.optimizeDeps, config.oxc)
  },
},

Hook filter 功能

Rolldown 引入了hook filter 功能,以减少 Rust 和 JavaScript 运行时之间的通信开销。通过使用此功能,您可以使您的插件更高效。Rollup 4.38.0+ 和 Vite 6.3.0+ 也支持此功能。为了使您的插件向后兼容旧版本,请确保也在钩子处理程序中运行过滤器。

提示

@rolldown/pluginutils 导出了一些用于 hook 过滤器的实用程序,例如 exactRegexprefixRegex

loadtransform 钩子中将内容转换为 JavaScript

如果您在 loadtransform 钩子中将内容从其他类型转换为 JavaScript,您可能需要在返回值中添加 moduleType: 'js'

js
const plugin = {
  name: 'txt-loader',
  load(id) {
    if (id.endsWith('.txt')) {
      const content = fs.readFile(id, 'utf-8')
      return {
        code: `export default ${JSON.stringify(content)}`,
        moduleType: 'js', 
      }
    }
  },
}

这是因为Rolldown 支持非 JavaScript 模块,除非另有说明,否则会从扩展名推断模块类型。

在 MIT 许可证下发布。(083ff36d)