Web開発
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コスト削減に貢献します。
全文翻訳
React Now Rusted All The Way Out
oxcチームが2026年8月4日に公式にRust製Reactコンパイラをサポートするリリースを行った後、私たちは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が、ビルドパイプラインの他の部分に関係なく、コードベースをReactコンパイルするための最小限のViteプラグインです。
高速なビルド = 幸せな開発者 + 安価なCI
この変更のヘッドライン機能は速度向上です。oxcプロジェクトリーダーのPer Boshenによると、「予備ベンチマークではBabelよりも10倍以上高速です。1,036ファイルをBabelでビルドした場合の14.3秒から、ネイティブ(シングルスレッド)では0.81秒へと、17倍以上の速度向上を確認しました。これは私たちにとって非常に大きなことです。なぜなら、エージェント支援ソフトウェア開発によってもたらされる変化の速さにより、CIの使用量とGitHub Actionsの時間は実際のコストセンターとなっており、CIを待つのは気分が悪く、すでに過度に断片化されたタスク管理の脳にさらなるプレッシャーを与えているからです。」これらの速度向上はビルドプロセスのコンパイラ部分にのみ適用されることに注意してください。ビルド中には他にも多くの処理が行われているため、全体的なビルド時間の改善はそれほど劇的ではありません。私たちのケースでは、ビルドは約2.4倍高速になりました(22.1秒→9.3秒)。
Reactコンパイラの制限について
速度がヘッドライナーであるにもかかわらず、私は最新かつ最高のReactコンパイラバージョンの利点にさらに興奮しています。これは、BabelベースのReactコンパイラのv1.0にまだ存在していたJavaScriptサポートのいくつかの重大な制限をすでに修正しています。これには、try/catchブロック内のあらゆる種類の条件付きロジックのサポートが含まれており、コンパイラの最初の安定版v1.0では多くの人にとってブロックとなっていました。また、執筆時点で先週着陸したもう一つの良い修正は、分割されたコンポーネントプロップを再代入し、それをネストされたクロージャで使用するパターンのサポートです。例:
export default function Foo({ value }: { value: null | string }) {
value = value ?? "this is a fallback";
return <button onClick={() => console.log(value)}>{value}</button>;
}
コード言語: JavaScript (javascript)
以前はスキップされていましたが、現在は完全にサポートされています。3つ目の一般的なパターンで、Babelコンパイラでバックアウトを引き起こしていたのは、計算されたオブジェクトプロパティキーです。例:
import { clsx } from "clsx";
export default function Header({ itemCount }: { itemCount: number }) {
return (
<header className={clsx({
[`items-${itemCount}`]: itemCount > 0
})}>
{/* ... */}
</header>
);
}
コード言語: JavaScript (javascript)
これらの修正により、新しいバージョンは私たちのアプリでのコンパイラ互換性をさらに7つの関数拡張します。try/catchの改善により5つ、計算されたオブジェクトプロパティキーにより2つです。明確にしておくと、まだサポートされていない制限があります。私が遭遇した、コンパイラがコンポーネント/フックをスキップさせる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()]
})
],
});
コード言語: JavaScript (javascript)
ネイティブ化するということは、設定のデッドウェイトを捨てることを意味します。以下を実行します。
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 })
],
});
コード言語: JavaScript (javascript)
これにより、package.jsonのdev依存関係から@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 = {
/* optional config if you have it */
};
export default defineConfig({
plugins: [
reactRouter(),
babel({
babelConfig: {
presets: ["@babel/preset-typescript"], // if you use TypeScript
plugins: [["babel-plugin-react-compiler", ReactCompilerConfig]],
},
exclude: /node_modules/,
include: /\.[jt]sx?$/,
}),
],
});
コード言語: JavaScript (javascript)
現在では、vite-plugin-babel、babel-plugin-react-compiler、@babel/preset-typescriptを完全に削除し、代わりに以下をインストールするだけです。
npm install -D @acusti/vite-plugin-react-compiler
コード言語: Bash (bash)
そして設定を以下のように簡素化します。
// 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(),
// or, if you need to pass custom compiler config:
// reactCompiler({ compiler: { /* your existing ReactCompilerConfig */ } })
],
});
コード言語: JavaScript (javascript)
よりシンプルで、より高速で、より高機能になりました。それに乾杯。ちょうど良い飲み物がわかった気がします。