Rust製ReactコンパイラがViteにネイティブ対応
The Rust React Compiler is now native in Vite (blog.master.dev)
要約
oxcチームによるRust製Reactコンパイラの公式サポート開始を受け、Viteのプラグインシステムがネイティブ対応しました。これにより、ビルドコンパイラ部分で最大17.6倍の速度向上が報告されています。Rust版は、Babel版にあった条件付きロジックやプロパティキーのサポートなど、JavaScriptの互換性に関する制限も解消しており、開発者体験とCIコスト削減に貢献します。
全文翻訳
Rust製ReactコンパイラがViteでネイティブ対応
oxcチームがRust製Reactコンパイラの公式サポートを2026年8月4日にリリースした後、私たちは1,036ファイルからなるReact Routerのコードベース(Outlyne、ウェブサイトビルダー)をそれに切り替え、コンパイラ部分のビルドで約17.6倍の高速化を達成しました。
@vitejs/plugin-react の v6.1.0リリース は「実験的なネイティブReactコンパイラサポート」をもたらしました。これは、Viteの設定でプラグインに { compiler: true } を渡すことでオプトインできます。また、Vite Reactプラグインを使用できない場合(例えば、私たちのようにフレームワークモードでReact Routerを使用している場合)は、[@acusti/vite-plugin-react-compiler](https://www.npmjs.com/package/@acusti/vite-plugin-react-compiler) という最小限のViteプラグインを使用することで、ビルドパイプライン全体に関わらずコードベースをReactコンパイルできます。
より高速なビルド = より幸せな開発者 + より安価なCI
この変更の目玉機能は速度向上です。oxcプロジェクトリーダーのBoshen氏 によると:
事前ベンチマークでは、Babelの10倍以上の速度が出ています。
私たちは17倍以上の高速化を目の当たりにしました。1,036ファイルがBabelでビルドした場合の14.3秒から、ネイティブ(シングルスレッド)では0.81秒になりました。これは私たちにとって非常に大きなことです。エージェント支援によるソフトウェア開発がもたらす変化の速さにより、CIの使用時間やGitHub Actionsの分数は現実的なコストセンターとなっており、CIを待つことは残念なだけでなく、すでに過度に断片化されたタスク管理の脳にさらなるプレッシャーを与えます。
これらの高速化はビルドプロセスのコンパイラ部分にのみ適用されることに注意してください。ビルド中には他にも多くの処理が行われているため、全体のビルド時間への影響はそれほど劇的ではないでしょう。私たちのケースでは、ビルドは約2.4倍高速化しました(22.1秒 → 9.3秒)。
Reactコンパイラの制限事項は?
速度がヘッドライナーであるにもかかわらず、私は最新かつ最高のReactコンパイラバージョンを使用することのメリットに最も興奮しています。このバージョンは、BabelベースのReactコンパイラのv1.0にまだ存在していたJavaScriptサポートにおけるいくつかの重大な制限をすでに修正しています。これには、try/catchブロック内のあらゆる種類の条件ロジックのサポートが含まれます。これは、コンパイラの初期安定版1.0リリースで多くの人にとってブロッカーでした。もう一つの便利な修正は、執筆時点で先週にマージされたもので、分割代入されたコンポーネントプロップを再代入し、それがネストされたクロージャで使用される場合のサポートです。例:
export default function Foo({ value }: { value: null | string }) {
value = value ?? "this is a fallback";
return <button onClick={() => console.log(value)}>{value}</button>;
}
以前はスキップされていましたが、現在は完全にサポートされています。Babelコンパイラでバグを引き起こした3つ目の一般的なパターンで、現在サポートされているのは算出オブジェクトプロパティキーです。例:
import { clsx } from "clsx";
export default function Header({ itemCount }: { itemCount: number }) {
return (
<header className={clsx({ [`items-${itemCount}`]: itemCount > 0 }) }>
{/* ... */}
</header>
);
}
これらの修正により、新しいバージョンは私たちのアプリでのコンパイラ互換性をさらに7つの関数拡張します。try/catchの改善により5つ、算出オブジェクトプロパティキーにより2つです。明確にしておくと、まだサポートされていない制限事項は存在します。コンポーネント/フックがスキップされる原因となるパターンとして私が遭遇したものは、tryブロック内からのthrowと、論理代入演算子(??=, &&=, ||=)です。しかし、Rustコンパイラを使用することで、これらの修正がリリースされたときにそれらを入手できます。行き止まりのBabelベースコンパイラに stuck している場合は、そのような幸運はありません。
ツールチェーンの一貫性 = カバレッジギャップなし
私がビルドを切り替えることに興奮している最後の理由は、私の完全なツールチェーンがReactコンパイラの同じバージョンと等価な機能サポートを使用するようになったことです。ビルドでReactコンパイラの古いバージョンを使用しながらOxlintのReactコンパイラサポートを採用した後、前述の分割代入されたコンポーネントプロップのバグについて、oxcに誤ったイシューを報告しました。コンポーネントはビルド時に最適化されませんでしたが、リンターエラーも発生しなかったため、コンパイラ出力とのリンターの不一致があると考えていました。実際には、Oxlintがoxc-transform-react v0.145.0を使用しており、そのパターンをサポートしていましたが、私がテストしていたのは同じパッケージのv0.144.0でした。
現在、リンターとビルドは全く同じReactコンパイラを使用しており、改善点と制限事項も同じであるため、未コンパイルのコンポーネントが本番ビルドに紛れ込む心配をする必要がありません。
使用方法
@vitejs/plugin-react を使用する場合
Vite v8以降を使用している限り、既存のReact ViteビルドをネイティブReactコンパイラに切り替えるのは、単純化するだけです。現在のBabelベースのreact.devの説明では、以下を実行するように指定されています:
npm install -D @rolldown/plugin-babel
以下のVite設定と共に:
// vite.config.js
import { defineConfig } from "vite";
import react, { reactCompilerPreset } from "@vitejs/plugin-react";
import babel from "@rolldown/plugin-babel";
export default defineConfig({
plugins: [react(), babel({ presets: [reactCompilerPreset()] })],
});
ネイティブ化するということは、設定のデッドウェイトを捨てることを意味します。以下を実行します:
npm install -D oxc-transform-react
そしてVite設定を単純化します:
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react({ compiler: true })],
});
これにより、package.json の開発依存関係から@rolldown/plugin-babelを削除することもできます。
@vitejs/plugin-react を使用しない場合(例: React Router Framework Mode)
React Routerをフレームワークモードで使用しているコードベースの場合、切り替えは少し異なります。React Routerには独自のViteプラグインがあり、これはVite Reactプラグインの代わりに使用する必要があります。そのため、以前は以下を実行する必要がありました:
npm install -D vite-plugin-babel babel-plugin-react-compiler @babel/preset-typescript
以下のVite設定と共に:
// vite.config.js
import { defineConfig } from "vite";
import babel from "vite-plugin-babel";
import { reactRouter } from "@react-router/dev/vite";
const ReactCompilerConfig = {
/* オプション設定があればここに */
};
export default defineConfig({
plugins: [
reactRouter(),
babel({
babelConfig: {
presets: ["@babel/preset-typescript"], // TypeScriptを使用する場合
plugins: [["babel-plugin-react-compiler", ReactCompilerConfig]],
},
exclude: /node_modules/,
include: /\.[jt]sx?$/,
}),
],
});
現在は、vite-plugin-babel、babel-plugin-react-compiler、@babel/preset-typescript を完全に削除し、代わりに以下をインストールするだけです:
npm install -D @acusti/vite-plugin-react-compiler
そして設定を以下のように単純化します:
// vite.config.js
import { defineConfig } from "vite";
import reactCompiler from "@acusti/vite-plugin-react-compiler";
import { reactRouter } from "@react-router/dev/vite";
export default defineConfig({
plugins: [reactRouter(), reactCompiler()],
// または、カスタムコンパイラ設定を渡す必要がある場合:
// reactCompiler({ compiler: { /* 既存のReactCompilerConfig */ } })
});
よりシンプルに、より高速に、そしてより高機能に。それに乾杯。ちょうどぴったりの飲み物を知っていると思います。