4 серпня 2026 року команда oxc офіційно випустила підтримку React Compiler, переписаного на Rust. Розробники сайтбілдера Outlyne, чия кодова база на React Router складається з 1 036 файлів, одразу перейшли на нове рішення і отримали приблизно 17,6-кратне прискорення саме тієї частини збірки, що відповідає за компіляцію.

Версія 6.1.0 плагіна @vitejs/plugin-react додала «експериментальну нативну підтримку React Compiler», яку можна активувати, передавши { compiler: true } у налаштування плагіна у конфігурації Vite. Для тих, хто не може використовувати цей плагін напряму, наприклад через роботу з React Router у фреймворк-режимі, існує мінімалістичний плагін @acusti/vite-plugin-react-compiler, який дозволяє застосувати React-компіляцію незалежно від решти збіркового конвеєра.

Швидші збірки — задоволені розробники і дешевший CI

Головна перевага переходу — саме швидкість. Керівник проєкту oxc Boshen прокоментував це так:

It is more than 10 times faster than Babel in our preliminary benchmark.

Boshen, керівник проєкту oxc

У випадку команди Outlyne приріст виявився ще більшим — понад 17 разів. Компіляція 1 036 файлів, яка раніше на Babel займала 14,3 секунди, тепер виконується за 0,81 секунди в один потік. Для команди це критично важливо: через темпи змін, які приносить розробка з допомогою агентів, витрати на CI та хвилини GitHub Actions перетворилися на суттєву статтю бюджету, а очікування результатів CI лише посилює фрагментацію уваги розробників.

Варто зауважити, що згадане прискорення стосується лише етапу компіляції. Оскільки в загальній збірці відбувається ще багато інших процесів, підсумковий виграш у часі не настільки вражаючий. У випадку Outlyne загальна збірка стала швидшою приблизно у 2,4 рази — з 22,1 секунди до 9,3 секунди.

Що з обмеженнями React Compiler?

Хоча швидкість і привертає найбільше уваги, автора матеріалу більше надихають переваги роботи з найновішою версією React Compiler, у якій уже усунено низку суттєвих обмежень підтримки JavaScript, що залишалися навіть у версії 1.0 на базі Babel. Зокрема, тепер підтримується будь-яка умовна логіка всередині блоків try/catch — раніше саме це блокувало багатьох розробників після виходу стабільної версії 1.0 компілятора.

Ще одне корисне виправлення, яке з'явилося буквально минулого тижня на момент написання матеріалу, стосується перепризначення деструктурованого пропса компонента, який потім використовується у вкладеному замиканні. Раніше такий код призводив до пропуску оптимізації, тепер він повністю підтримується.

export default function Foo({ value }: { value: null | string }) {
  value = value ?? "this is a fallback";
  return {value};
}

Третій поширений шаблон, який раніше змушував Babel-компілятор відступати, а тепер підтримується, — це обчислювані ключі властивостей об'єктів.

import { clsx } from "clsx";

export default function Header({ itemCount }: { itemCount: number }) {
  return (
     0 })}>
      {/* ... */}
    
  );
}

Завдяки цим виправленням у застосунку Outlyne сумісність компілятора розширилася ще на сім функцій: п'ять — завдяки покращенню роботи з try/catch, дві — завдяки підтримці обчислюваних ключів об'єктів. Водночас обмеження досі залишаються. Автор виявив два шаблони, які й досі змушують компілятор пропускати компонент або хук: викид помилки (throw) всередині блоку try та логічні оператори присвоєння (??=, &&=, ||=). Проте перехід на Rust-компілятор гарантує, що ці виправлення з'являться, як тільки вийдуть, — на відміну від застарілого Babel-компілятора, розвиток якого зайшов у тупик.

Узгодженість інструментарію закриває прогалини в покритті

Ще одна причина, чому автор радий переходу, — тепер весь інструментарій використовує одну й ту саму версію React Compiler з однаковою підтримкою функцій. Раніше, коли він увімкнув підтримку React Compiler у Oxlint, але сама збірка ще працювала на старішій версії компілятора, він подав хибний баг-репорт до oxc через саме той випадок із деструктурованим пропсом, описаний вище: компонент не оптимізувався під час збірки, але й лінтер не показував помилки, що виглядало як розбіжність між лінтером і виводом компілятора. Виявилося, що Oxlint використовував пакет oxc-transform-react версії 0.145.0, який уже підтримував цей шаблон, тоді як сама збірка тестувалася на версії 0.144.0 того самого пакета.

Тепер лінтер і збірка використовують ідентичну версію React Compiler з однаковими покращеннями та обмеженнями, тож ризик того, що нескомпільований компонент потрапить у продакшн-збірку, зникає.

Як це підключити

Використання @vitejs/plugin-react

Якщо ви вже на Vite версії 8 і вище, перехід існуючої React-збірки на Vite до нативного React Compiler фактично зводиться до спрощення конфігурації. Поточна, побудована на Babel, інструкція з react.dev вимагає встановити:

npm install -D @rolldown/plugin-babel
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
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react({ compiler: true })],
});

Це також дозволяє видалити @rolldown/plugin-babel зі списку dev-залежностей у package.json.

Якщо @vitejs/plugin-react не використовується (наприклад, React Router у фреймворк-режимі)

Для кодових баз, що працюють на React Router у фреймворк-режимі, перехід виглядає трохи інакше. React Router має власний плагін для Vite, який має використовуватися замість плагіна React для Vite. Раніше для цього потрібно було встановити:

npm install -D vite-plugin-babel babel-plugin-react-compiler @babel/preset-typescript
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"],
        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
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()],
});

Простіше, швидше і функціональніше. Варто за це випити.

Джерело: Master.dev Blog