The default Vite plugin for React projects enabling Fast Refresh and flexible Babel integration
The official Vite plugin for React with Fast Refresh, automatic JSX runtime, and optional Babel integration.
Installation: npm install @vitejs/plugin-react
Basic Setup:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});Requirements:
Performance Decision Matrix:
| Scenario | Use Babel? | Transformer | Performance |
|---|---|---|---|
| Standard React app | No | esbuild/oxc | Fastest |
| Custom JSX import (Emotion) | No | esbuild/oxc | Fast |
| Need Babel plugins | Yes | Babel + esbuild | Slower |
| Parser-only features | Yes (parserOpts only) | esbuild/oxc | Fast |
import react from '@vitejs/plugin-react';
// TypeScript types
import type {
Options,
BabelOptions,
ReactBabelOptions,
ViteReactPluginApi
} from '@vitejs/plugin-react';function react(opts?: Options): Plugin[];
interface Options {
include?: string | RegExp | Array<string | RegExp>; // default: /\.[tj]sx?$/
exclude?: string | RegExp | Array<string | RegExp>; // default: /\/node_modules\//
jsxImportSource?: string; // default: 'react'
jsxRuntime?: 'classic' | 'automatic'; // default: 'automatic'
babel?: BabelOptions | ((id: string, options: { ssr?: boolean }) => BabelOptions);
reactRefreshHost?: string; // for module federation
}Common Configurations:
// Emotion support
react({ jsxImportSource: '@emotion/react' })
// Classic JSX runtime (requires React imports)
react({ jsxRuntime: 'classic' })
// Additional file types
react({ include: /\.(mdx|js|jsx|ts|tsx)$/ })
// Module federation
react({ reactRefreshHost: 'http://localhost:3000' })For SSR apps not using transformIndexHtml:
import '@vitejs/plugin-react/preamble';Usage:
// entry.client.tsx
import '@vitejs/plugin-react/preamble';
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);Error if missing:
Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong.Access preamble code:
react.preambleCode: string;Babel is lazy-loaded and only used when configured. Without Babel config, esbuild/oxc handles all transformations (fastest path).
For detailed Babel configuration, including:
See: Babel Integration
Quick Babel Examples:
// Add Babel plugins
react({
babel: {
plugins: ['babel-plugin-macros']
}
})
// Parser plugins only (no transformation overhead)
react({
babel: {
parserOpts: {
plugins: ['decorators-legacy']
}
}
})
// Dynamic configuration
react({
babel: (id, { ssr }) => ({
plugins: ssr ? ['babel-plugin-ssr'] : ['babel-plugin-client']
})
})The plugin factory returns multiple Vite plugins that work together:
Environment detection is automatic (Vite/Rolldown-vite, dev/prod).
Auto-enabled in development for files with JSX or React imports.
Requirements for proper Fast Refresh:
Linting: Use eslint-plugin-react-refresh
Automatic (default):
Classic:
import React in all JSX filesjsxRuntime: 'classic'Enable HMR across remote and host apps:
// Remote app vite.config.ts
react({ reactRefreshHost: 'http://localhost:3000' })Updates Fast Refresh runtime from /@react-refresh to http://localhost:3000/@react-refresh.
Note: Include base option if host uses it: http://localhost:3000/{base}
Transformation Matrix:
| Babel Config | Dev Transformer | Prod Transformer | Speed | Use Case |
|---|---|---|---|---|
| None | esbuild | esbuild | Fastest | Standard React app |
| parserOpts only | esbuild | esbuild | Fast | Parsing experimental syntax |
| plugins/presets | Babel | Babel | Slower | Custom transformations needed |
include/exclude options to reduce files processed by BabelIn production builds:
The plugin is compatible with Babel 7.x (specifically @babel/core ^7.28.4).
TypeScript syntax is automatically handled without configuration. You don't need @babel/preset-typescript unless you have specific TypeScript transformation requirements beyond standard syntax support.
When you might need @babel/preset-typescript:
Requires Node.js ^20.19.0 || >=22.12.0
Error: @vitejs/plugin-react can't detect preambleSolution: Add import '@vitejs/plugin-react/preamble' to client entry or use transformIndexHtml in SSR.
Check:
include pattern (default: /.[tj]sx?$/)If builds are slow:
include/exclude patternsTypeScript syntax is automatically handled by esbuild/oxc. You don't need @babel/preset-typescript unless you have specific transformation requirements beyond standard TypeScript syntax.
Package: @vitejs/plugin-react Type: npm Language: TypeScript (ESM with CommonJS compatibility) Docs: https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react
Babel Compatibility: @babel/core ^7.28.4 React Compatibility: >= 16.9 (< 16.9 works without Fast Refresh)
Install with Tessl CLI
npx tessl i tessl/npm-vitejs--plugin-react