Skip to content

Commit 133d786

Browse files
sapphi-redhi-ogawa
andauthored
feat: merge plugin-react-oxc into plugin-react (#609)
Co-authored-by: Hiroshi Ogawa <[email protected]>
1 parent edadfef commit 133d786

File tree

18 files changed

+128
-103
lines changed

18 files changed

+128
-103
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ jobs:
9393
- name: Test SWC
9494
run: pnpm --filter ./packages/plugin-react-swc run test
9595

96+
- name: Setup rolldown-vite
97+
run: |
98+
sed -i"" -e "s/overrides:/overrides:\n vite: catalog:rolldown-vite/" pnpm-workspace.yaml
99+
pnpm i --no-frozen-lockfile
100+
101+
- name: Test serve (rolldown-vite)
102+
run: pnpm run test-serve
103+
104+
- name: Test build (rolldown-vite)
105+
run: pnpm run test-build
106+
96107
lint:
97108
if: github.repository == 'vitejs/vite-plugin-react'
98109
timeout-minutes: 10

packages/plugin-react-oxc/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Deprecate this plugin
6+
7+
The changes of this plugin is now included in `@vitejs/plugin-react`. Please use `@vitejs/plugin-react` instead.
8+
59
### Allow processing files in `node_modules`
610

711
The default value of `exclude` options is now `[/\/node_modules\//]` to allow processing files in `node_modules` directory. It was previously `[]` and files in `node_modules` was always excluded regardless of the value of `exclude` option.

packages/plugin-react-oxc/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ export default function viteReact(opts: Options = {}): Plugin[] {
6262
},
6363
}
6464
},
65+
configResolved(config) {
66+
config.logger.warn(
67+
'@vitejs/plugin-react-oxc is deprecated. ' +
68+
'Please use @vitejs/plugin-react instead. ' +
69+
'The changes of this plugin is now included in @vitejs/plugin-react.',
70+
)
71+
},
6572
options() {
6673
if (!this.meta.rolldownVersion) {
6774
throw new Error(

packages/plugin-react-swc/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ type Options = {
7878
useAtYourOwnRisk_mutateSwcOptions?: (options: SWCOptions) => void
7979

8080
/**
81-
* If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
81+
* If set, disables the recommendation to use `@vitejs/plugin-react`
8282
*/
8383
disableOxcRecommendation?: boolean
8484
}
@@ -158,7 +158,7 @@ const react = (_options?: Options): Plugin[] => {
158158
!options.disableOxcRecommendation
159159
) {
160160
config.logger.warn(
161-
'[vite:react-swc] We recommend switching to `@vitejs/plugin-react-oxc` for improved performance as no swc plugins are used. More information at https://vite.dev/rolldown',
161+
'[vite:react-swc] We recommend switching to `@vitejs/plugin-react` for improved performance as no swc plugins are used. More information at https://vite.dev/rolldown',
162162
)
163163
}
164164
},

packages/plugin-react/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## Unreleased
44

5+
### Use Oxc for react refresh transform in rolldown-vite
6+
7+
When used with rolldown-vite, this plugin now uses Oxc for react refresh transform.
8+
9+
Since this behavior is what `@vitejs/plugin-react-oxc` did, `@vitejs/plugin-react-oxc` is now deprecated and the `disableOxcRecommendation` option is removed.
10+
511
### Allow processing files in `node_modules`
612

713
The default value of `exclude` options is now `[/\/node_modules\//]` to allow processing files in `node_modules` directory. It was previously `[]` and files in `node_modules` was always excluded regardless of the value of `exclude` option.

packages/plugin-react/src/index.ts

Lines changed: 84 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as vite from 'vite'
88
import type { Plugin, ResolvedConfig } from 'vite'
99
import {
1010
addRefreshWrapper,
11+
avoidSourceMapOption,
1112
getPreambleCode,
1213
preambleCode,
1314
runtimePublicPath,
@@ -58,11 +59,6 @@ export interface Options {
5859
* reactRefreshHost: 'http://localhost:3000'
5960
*/
6061
reactRefreshHost?: string
61-
62-
/**
63-
* If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
64-
*/
65-
disableOxcRecommendation?: boolean
6662
}
6763

6864
export type BabelOptions = Omit<
@@ -115,6 +111,8 @@ export default function viteReact(opts: Options = {}): Plugin[] {
115111
const jsxImportSource = opts.jsxImportSource ?? 'react'
116112
const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`
117113
const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`
114+
115+
const isRolldownVite = 'rolldownVersion' in vite
118116
let runningInVite = false
119117
let isProduction = true
120118
let projectRoot = process.cwd()
@@ -133,37 +131,53 @@ export default function viteReact(opts: Options = {}): Plugin[] {
133131
const viteBabel: Plugin = {
134132
name: 'vite:react-babel',
135133
enforce: 'pre',
136-
config() {
137-
if (opts.jsxRuntime === 'classic') {
138-
if ('rolldownVersion' in vite) {
134+
config(_userConfig, { command }) {
135+
if ('rolldownVersion' in vite) {
136+
if (opts.jsxRuntime === 'classic') {
139137
return {
140138
oxc: {
141139
jsx: {
142140
runtime: 'classic',
141+
refresh: command === 'serve',
143142
// disable __self and __source injection even in dev
144143
// as this plugin injects them by babel and oxc will throw
145144
// if development is enabled and those properties are already present
146145
development: false,
147146
},
147+
jsxRefreshInclude: include,
148+
jsxRefreshExclude: exclude,
148149
},
149150
}
150151
} else {
151152
return {
152-
esbuild: {
153-
jsx: 'transform',
153+
oxc: {
154+
jsx: {
155+
runtime: 'automatic',
156+
importSource: jsxImportSource,
157+
refresh: command === 'serve',
158+
development: command === 'serve',
159+
},
160+
jsxRefreshInclude: include,
161+
jsxRefreshExclude: exclude,
154162
},
163+
optimizeDeps: { rollupOptions: { jsx: { mode: 'automatic' } } },
155164
}
156165
}
166+
}
167+
168+
if (opts.jsxRuntime === 'classic') {
169+
return {
170+
esbuild: {
171+
jsx: 'transform',
172+
},
173+
}
157174
} else {
158175
return {
159176
esbuild: {
160177
jsx: 'automatic',
161-
jsxImportSource: opts.jsxImportSource,
178+
jsxImportSource: jsxImportSource,
162179
},
163-
optimizeDeps:
164-
'rolldownVersion' in vite
165-
? { rollupOptions: { jsx: { mode: 'automatic' } } }
166-
: { esbuildOptions: { jsx: 'automatic' } },
180+
optimizeDeps: { esbuildOptions: { jsx: 'automatic' } },
167181
}
168182
}
169183
},
@@ -180,17 +194,6 @@ export default function viteReact(opts: Options = {}): Plugin[] {
180194
.map((plugin) => plugin.api?.reactBabel)
181195
.filter(defined)
182196

183-
if (
184-
'rolldownVersion' in vite &&
185-
!opts.babel &&
186-
!hooks.length &&
187-
!opts.disableOxcRecommendation
188-
) {
189-
config.logger.warn(
190-
'[vite:react-babel] We recommend switching to `@vitejs/plugin-react-oxc` for improved performance. More information at https://vite.dev/rolldown',
191-
)
192-
}
193-
194197
if (hooks.length > 0) {
195198
runPluginOverrides = (babelOptions, context) => {
196199
hooks.forEach((hook) => hook(babelOptions, context, config))
@@ -252,7 +255,7 @@ export default function viteReact(opts: Options = {}): Plugin[] {
252255
? importReactRE.test(code)
253256
: code.includes(jsxImportDevRuntime) ||
254257
code.includes(jsxImportRuntime)))
255-
if (useFastRefresh) {
258+
if (useFastRefresh && !isRolldownVite) {
256259
plugins.push([
257260
await loadPlugin('react-refresh/babel'),
258261
{ skipEnvCheck: true },
@@ -329,6 +332,59 @@ export default function viteReact(opts: Options = {}): Plugin[] {
329332
},
330333
}
331334

335+
const viteRefreshWrapper: Plugin = {
336+
name: 'vite:react:refresh-wrapper',
337+
apply: 'serve',
338+
transform: isRolldownVite
339+
? {
340+
filter: {
341+
id: {
342+
include: makeIdFiltersToMatchWithQuery(include),
343+
exclude: makeIdFiltersToMatchWithQuery(exclude),
344+
},
345+
},
346+
handler(code, id, options) {
347+
const ssr = options?.ssr === true
348+
349+
const [filepath] = id.split('?')
350+
const isJSX = filepath.endsWith('x')
351+
const useFastRefresh =
352+
!skipFastRefresh &&
353+
!ssr &&
354+
(isJSX ||
355+
code.includes(jsxImportDevRuntime) ||
356+
code.includes(jsxImportRuntime))
357+
if (!useFastRefresh) return
358+
359+
const { code: newCode } = addRefreshWrapper(
360+
code,
361+
avoidSourceMapOption,
362+
'@vitejs/plugin-react',
363+
id,
364+
)
365+
return { code: newCode, map: null }
366+
},
367+
}
368+
: undefined,
369+
}
370+
371+
const viteConfigPost: Plugin = {
372+
name: 'vite:react:config-post',
373+
enforce: 'post',
374+
config(userConfig) {
375+
if (userConfig.server?.hmr === false) {
376+
return {
377+
oxc: {
378+
jsx: {
379+
refresh: false,
380+
},
381+
},
382+
// oxc option is only available in rolldown-vite
383+
} as any
384+
}
385+
},
386+
}
387+
332388
const dependencies = [
333389
'react',
334390
'react-dom',
@@ -384,7 +440,7 @@ export default function viteReact(opts: Options = {}): Plugin[] {
384440
},
385441
}
386442

387-
return [viteBabel, viteReactRefresh]
443+
return [viteBabel, viteRefreshWrapper, viteConfigPost, viteReactRefresh]
388444
}
389445

390446
viteReact.preambleCode = preambleCode

packages/plugin-rsc/e2e/starter.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect, test } from '@playwright/test'
22
import { useFixture } from './fixture'
33
import { defineStarterTest } from './starter'
44
import { waitForHydration } from './helper'
5+
import * as vite from 'vite'
56

67
test.describe('dev-default', () => {
78
const f = useFixture({ root: 'examples/starter', mode: 'dev' })
@@ -24,6 +25,8 @@ test.describe('build-cloudflare', () => {
2425
})
2526

2627
test.describe('dev-production', () => {
28+
test.skip('rolldownVersion' in vite)
29+
2730
const f = useFixture({
2831
root: 'examples/starter',
2932
mode: 'dev',
@@ -42,6 +45,8 @@ test.describe('dev-production', () => {
4245
})
4346

4447
test.describe('build-development', () => {
48+
test.skip('rolldownVersion' in vite)
49+
4550
const f = useFixture({
4651
root: 'examples/starter',
4752
mode: 'build',

playground/class-components/__tests__/oxc/class-components.spec.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

playground/hmr-false/__tests__/oxc/hmr-false.spec.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

playground/hook-with-jsx/__tests__/oxc/hook-with-jsx.spec.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)