После того как команда oxc выпустила официальную поддержку React Compiler на Rust 4 августа 2026 года, она перенесла кодовую базу React Router из 1036 файлов (Outlyne, конструктор сайтов) на новый компилятор и получила ускорение ~17,6× на этапе компиляции.

В релизе v6.1.0 плагина @vitejs/plugin-react появилась "экспериментальная поддержка нативного React Compiler". Включить её можно, передав { compiler: true } в конфигурацию Vite. Для тех, кто не может использовать плагин (например, при использовании React Router в режиме фреймворка), есть @acusti/vite-plugin-react-compiler — минимальный Vite-плагин для компиляции React независимо от остального конвейера сборки.

Быстрее собирается — разработчики довольнее, CI дешевле

Главное изменение — это скорость. По словам Босена, ведущего разработчика oxc:

Это более чем в 10 раз быстрее, чем Babel, согласно нашим предварительным тестам.

Результаты показали ускорение более чем в 17 раз: 1036 файлов компилировались за 14,3 с с Babel, а нативно — за 0,81 с (однопоточно). Для разработки это критично, потому что с быстрым изменением кода (особенно при AI-ассистентах) затраты на CI и GitHub Actions становятся существенными, а ожидание сборки отвлекает внимание.

Важно понимать: такое ускорение касается только компилятора. Во время сборки обычно запускается много других процессов, поэтому общее время собирания будет улучшено не так сильно. В данном случае вся сборка ускорилась в 2,4 раза (22,1 с → 9,3 с).

Но у React Compiler есть ограничения?

Хотя скорость — главное преимущество, большинство волнует другое: новая версия Rust-компилятора уже исправила существенные проблемы в поддержке JavaScript, которые были в v1.0 Babel-версии. Это включает поддержку условной логики в блоках 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-компиляторе и теперь поддерживаемый — вычисляемые ключи свойств объекта:

import { clsx } from "clsx";

export default function Header({ itemCount }: { itemCount: number }) {
  return (
    <header className={clsx({ [`items-${itemCount}`]: itemCount > 0 })}>
      {/* ... */}
    </header>
  );
}

Благодаря этим исправлениям совместимость компилятора в приложении расширилась на семь функций: пять благодаря улучшению try/catch, две — благодаря поддержке вычисляемых ключей. Конечно, ограничения остаются. Две конструкции, которые всё ещё заставляют компилятор пропускать компоненты и хуки — это throw из блока try и операторы логического присваивания (??=, &&=, ||=). Но переход на Rust-компилятор гарантирует, что исправления будут получены сразу же, когда они выйдут. С мёртвым Babel-компилятором такого не будет.

Единая версия в toolchain — никаких пробелов в покрытии

Последняя причина для переезда — полный toolchain теперь использует одну и ту же версию React Compiler с одинаковой поддержкой функций. После того как линтер Oxlint получил поддержку React Compiler, но сборка всё ещё использовала более старую версию, был подан некорректный баг-репорт в oxc: компонента не оптимизировалась во время сборки, но и ошибок линтера не было, поэтому казалось, что есть рассинхрон. Оказалось, что Oxlint использовал oxc-transform-react v0.145.0 (поддерживает нужный паттерн), а сборка — v0.144.0.

Теперь линтер и сборка используют один React Compiler с одинаковыми улучшениями и ограничениями, поэтому не нужно беспокоиться, что некомпилированные компоненты попадут в production.

Как использовать

С @vitejs/plugin-react

Если используется Vite v8+, переключение на нативный React Compiler — это просто упрощение конфигурации. Текущие инструкции на react.dev для Babel указывают запустить:

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 })],
});

Также можно удалить @rolldown/plugin-babel из dev-зависимостей в package.json.

Без @vitejs/plugin-react (например, React Router в режиме фреймворка)

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

npm install -D vite-plugin-babel babel-plugin-react-compiler @babel/preset-typescript

С такой конфигурацией:

// 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?$/,
    }),
  ],
});

Теперь можно полностью отказаться от 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: { /* your existing ReactCompilerConfig */ } })
});

Проще, быстрее и мощнее. За такое есть что отметить.