コンテンツへスキップ

Rolldownの統合

Viteは、ビルドパフォーマンスと機能を向上させるため、RustベースのJavaScriptバンドラーであるRolldownの統合を計画しています。

Rolldownとは?

Rolldownは、Rustで書かれた最新の高性能JavaScriptバンドラーです。Rollupの代替として設計されており、既存のエコシステムとの互換性を維持しながら、大幅なパフォーマンス向上を目指しています。

Rolldownは3つの主要な原則に焦点を当てています。

  • 速度: 最高のパフォーマンスを実現するためにRustで構築されています。
  • 互換性: 既存のRollupプラグインと連携します。
  • 最適化: esbuildやRollupが実装しているもの以上の機能が付属しています。

ViteがRolldownに移行する理由

  1. 統合: Viteは現在、依存関係の事前バンドルにesbuildを、本番ビルドにRollupを使用しています。Rolldownはこれらを単一の高性能バンドラーに統合し、両方の目的で使用できるようにすることで、複雑さを軽減することを目指しています。

  2. パフォーマンス: RolldownのRustベースの実装は、JavaScriptベースのバンドラーよりも大幅なパフォーマンス向上を実現します。特定のベンチマークはプロジェクトのサイズと複雑さによって異なりますが、初期のテストではRollupと比較して有望な速度向上が示されています。

  3. 追加機能: Rolldownは、高度なチャンク分割制御、組み込みのHMR、Module Federationなど、Rollupやesbuildにはない機能を提供します。

Rolldownの背後にある動機に関する追加の洞察については、Rolldownが構築されている理由を参照してください。

rolldown-viteを試す利点

  • 特に大規模なプロジェクトで、ビルド時間が大幅に短縮されます。
  • Viteのバンドル体験の未来を形作る貴重なフィードバックを提供できます。
  • 将来的なRolldownの正式統合に向けてプロジェクトを準備できます。

Rolldownの試用方法

Rolldownを搭載したViteのバージョンは、現在rolldown-viteという別のパッケージとして利用できます。viteを直接の依存関係として持っている場合、プロジェクトのpackage.jsonviteパッケージをrolldown-viteにエイリアスすることで、ドロップイン置換が可能です。

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

VitepressやViteをピア依存関係として持つメタフレームワークを使用している場合、package.jsonvite依存関係をオーバーライドする必要がありますが、これはパッケージマネージャーによって若干異なります。

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のドロップイン置換を目指していますが、まだ実装中の機能や、意図的な挙動の minor な違いがあります。包括的なリストについては、定期的に更新されているこのGitHub PRを参照してください。

オプション検証の警告

Rolldownは、未知または無効なオプションが渡された場合に警告を出力します。Rollupで利用可能な一部のオプションはRolldownでサポートされていないため、使用するオプションや使用するメタフレームワークが設定するオプションに基づいて警告に遭遇する可能性があります。以下に、そのような警告メッセージの例を示します。

警告:出力オプションを検証します。

  • "generatedCode"の場合。無効なキー: neverが期待されましたが、"generatedCode"を受け取りました。

オプションを自分で渡していない場合、これは使用しているフレームワークによって修正される必要があります。

APIの違い

manualChunks から advancedChunks

RolldownはRollupで利用可能だったmanualChunksオプションをサポートしていません。代わりに、webpackのsplitChunkに似た、advancedChunksオプションを介してよりきめ細かな設定を提供します。

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を使用している場合、BabelまたはSWCの代わりにOxcを使用してReactのfast-refreshを行う@vitejs/plugin-react-oxcプラグインに切り替えることができます。これはドロップイン置換として設計されており、より良いビルドパフォーマンスとrolldown-viteの基盤アーキテクチャとの整合性を提供します。

BabelまたはSWCプラグイン(Reactコンパイラを含む)を使用していない場合、またはSWCオプションを変更しない場合にのみ、@vitejs/plugin-react-oxcに切り替えることができることに注意してください。

withFilterラッパー

プラグイン作者は、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$/ } },
    ),
  ],
})

問題の報告

これは実験的な統合であるため、問題に遭遇する可能性があります。もし遭遇した場合は、メインのViteリポジトリではなくvitejs/rolldown-viteリポジトリに報告してください。

問題を報告する際は、適切な課題テンプレートに従い、通常以下を含む要求された情報を提供してください。

  • 問題の最小限の再現
  • 環境の詳細(OS、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が最初に導入された際の速度と人気の主な理由でした。このアプローチは、従来のバンドルなしで開発サーバーのパフォーマンスの限界をどこまで押し上げられるかを見るための最初の実験でした。

しかし、プロジェクトが規模と複雑さを増すにつれて、2つの主な課題が浮上してきました。

  1. 開発/本番環境の不整合: 開発環境で提供されるバンドルされていないJavaScriptと、バンドルされた本番ビルドでは、ランタイムの動作が異なります。これにより、本番環境でのみ発生する問題が生じ、デバッグがより困難になる可能性があります。

  2. 開発中のパフォーマンス低下: バンドルされていないアプローチでは、各モジュールが個別にフェッチされるため、多数のネットワークリクエストが発生します。これは本番環境では影響しませんが、開発サーバーの起動時や開発中にページを更新する際にかなりのオーバーヘッドを引き起こします。この影響は、数百または数千もの個別のリクエストを処理する必要がある大規模なアプリケーションで特に顕著です。開発者がネットワークプロキシを使用すると、これらのボトルネックはさらに深刻になり、更新時間が遅くなり、開発者エクスペリエンスが低下します。

Rolldownの統合により、Viteの特徴的なパフォーマンスを維持しながら、開発と本番環境のエクスペリエンスを統合する機会が得られます。フルバンドルモードでは、本番環境だけでなく開発中にもバンドルされたファイルを提供できるようになり、両方の利点を組み合わせることができます。

  • 大規模なアプリケーションでも高速な起動時間
  • 開発環境と本番環境間の一貫した動作
  • ページ更新時のネットワークオーバーヘッドの削減
  • ESM出力のEfficient HMRを維持

フルバンドルモードが導入される場合、最初はオプトイン機能となります。Rolldownの統合と同様に、フィードバックを収集し、安定性を確保した後、デフォルトにする予定です。

プラグイン / フレームワーク作者向けガイド

ヒント

このセクションは主にプラグインおよびフレームワークの作者向けです。ユーザーの方はこのセクションをスキップできます。

主な変更点の概要

  • ビルドにはRolldownが使用されます(以前はRollupが使用されていました)。
  • オプティマイザにはRolldownが使用されます(以前はesbuildが使用されていました)。
  • CommonJSのサポートはRolldownによって処理されます(以前は@rollup/plugin-commonjsが使用されていました)。
  • 構文の低レベル化にはOxcが使用されます(以前はesbuildが使用されていました)。
  • CSSのミニファイにはデフォルトでLightning CSSが使用されます(以前はesbuildが使用されていました)。
  • JSのミニファイにはデフォルトでOxcミニファイアが使用されます(以前はesbuildが使用されていました)。
  • 設定ファイルのバンドルにはRolldownが使用されます(以前はesbuildが使用されていました)。

rolldown-viteの検出

警告

ほとんどの場合、プラグインがrolldown-viteまたはviteのどちらで実行されているかを検出する必要はなく、条件分岐なしで両方で一貫した動作を目指すべきです。

rolldown-viteで異なる動作が必要な場合、rolldown-viteが使用されているかどうかを検出する方法が2つあります。

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はすべてのフックで利用可能です。以前のバージョンでは、configフックなどのVite固有のフックではthis.metaは利用できませんでした。


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を依存関係に追加するか、ユーザーが手動でインストールする必要があります。

推奨される移行方法は、esbuildの代わりにOxcを利用する、新しくエクスポートされたtransformWithOxc関数を使用することです。

esbuildオプションの互換レイヤー

Rolldown-Viteには、esbuildのオプションをそれぞれのOxcまたはrolldownのオプションに変換するための互換レイヤーがあります。エコシステムCIでテストされたように、これは単純なesbuildプラグインを含む多くのケースで機能します。とは言え、将来的にはesbuildオプションのサポートを削除する予定ですので、対応するOxcまたはrolldownオプションを試すことをお勧めします。互換レイヤーによって設定されたオプションは、configResolvedフックから取得できます。

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

フックフィルター機能

Rolldownは、RustとJavaScriptランタイム間の通信オーバーヘッドを削減するために、フックフィルター機能を導入しました。この機能を使用することで、プラグインのパフォーマンスを向上させることができます。これはRollup 4.38.0以降およびVite 6.3.0以降でもサポートされています。プラグインを古いバージョンとの下位互換性を持たせるには、フックハンドラー内でもフィルターを実行するようにしてください。

ヒント

@rolldown/pluginutilsは、exactRegexprefixRegexなどのフックフィルター用のユーティリティをいくつかエクスポートしています。

loadまたはtransformフックでコンテンツをJavaScriptに変換する場合

loadまたはtransformフックでコンテンツを他の型から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)