Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions .github/workflows/ci-rsc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,18 @@ jobs:
- run: pnpm -C packages/plugin-rsc test

test-e2e:
name: test-rsc (${{ matrix.os }} / ${{ matrix.browser }}) ${{ matrix.rolldown == true && '(rolldown)' || '' }} ${{ matrix.react_version && format('(react-{0})', matrix.react_version) || '' }}
name: test-rsc (${{ matrix.os }} / ${{ matrix.browser }}) ${{ matrix.react_version && format('(react-{0})', matrix.react_version) || '' }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
browser: [chromium]
rolldown: [false]
react_version: ['']
include:
- os: ubuntu-latest
browser: firefox
- os: macos-latest
browser: webkit
- os: ubuntu-latest
browser: chromium
rolldown: true
- os: ubuntu-latest
browser: chromium
react_version: canary
Expand All @@ -75,11 +71,6 @@ jobs:
env:
REACT_VERSION: ${{ matrix.react_version }}
- run: pnpm build
- name: install rolldown
if: ${{ matrix.rolldown }}
run: |
yq -i '.overrides.vite = "beta"' pnpm-workspace.yaml
pnpm i --no-frozen-lockfile
- run: pnpm -C packages/plugin-rsc exec playwright install "$BROWSER_NAME"
shell: bash
env:
Expand All @@ -91,7 +82,7 @@ jobs:
- uses: actions/upload-artifact@v6
if: always()
with:
name: test-results-${{ matrix.os }}-${{ matrix.browser }}${{ matrix.rolldown == true && '-rolldown' || '' }}${{ matrix.react_version && format('-react-{0}', matrix.react_version) || '' }}
name: test-results-${{ matrix.os }}-${{ matrix.browser }}${{ matrix.react_version && format('-react-{0}', matrix.react_version) || '' }}
path: |
packages/plugin-rsc/test-results
if-no-files-found: ignore
11 changes: 0 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,6 @@ jobs:
- name: Test SWC
run: pnpm --filter ./packages/plugin-react-swc run test

- name: Setup rolldown-vite
run: |
sed -i"" -e "s/overrides:/overrides:\n vite: catalog:rolldown-vite/" pnpm-workspace.yaml
pnpm i --no-frozen-lockfile

- name: Test serve (rolldown-vite)
run: pnpm run test-serve

- name: Test build (rolldown-vite)
run: pnpm run test-build

lint:
if: github.repository == 'vitejs/vite-plugin-react'
timeout-minutes: 10
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"simple-git-hooks": "^2.13.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.56.0",
"vite": "^7.3.1",
"vite": "^8.0.0-beta.16",
"vite-plugin-inspect": "^11.3.3",
"vitest": "^4.0.18"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
"@rolldown/pluginutils": "1.0.0-rc.5"
},
"peerDependencies": {
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
}
}
8 changes: 4 additions & 4 deletions packages/plugin-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
"@rolldown/pluginutils": "1.0.0-rc.5",
"@types/babel__core": "^7.20.5",
"react-refresh": "^0.18.0"
"@types/babel__core": "^7.20.5"
},
"devDependencies": {
"@vitejs/react-common": "workspace:*",
"babel-plugin-react-compiler": "19.1.0-rc.3",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"rolldown": "1.0.0-rc.5",
"tsdown": "^0.20.3"
"tsdown": "^0.20.3",
"vite": "^8.0.0-beta.16"
},
"peerDependencies": {
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
"vite": "^8.0.0"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
Expand Down
1 change: 0 additions & 1 deletion packages/plugin-react/src/babel.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
declare module '@babel/plugin-transform-react-jsx-self'
declare module '@babel/plugin-transform-react-jsx-source'
declare module 'react-refresh/babel.js'
169 changes: 31 additions & 138 deletions packages/plugin-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
makeIdFiltersToMatchWithQuery,
} from '@rolldown/pluginutils'
import {
addRefreshWrapper,
getPreambleCode,
preambleCode,
runtimePublicPath,
Expand All @@ -17,7 +16,7 @@ import {
} from '@vitejs/react-common'
import type { Plugin, ResolvedConfig } from 'vite'
import { createFilter } from 'vite'
import * as vite from 'vite'
import { reactRefreshWrapperPlugin } from 'vite/internal'

const _dirname = dirname(fileURLToPath(import.meta.url))
const refreshRuntimePath = join(_dirname, 'refresh-runtime.js')
Expand Down Expand Up @@ -47,7 +46,7 @@ export interface Options {
exclude?: string | RegExp | Array<string | RegExp>
/**
* Control where the JSX factory is imported from.
* https://esbuild.github.io/api/#jsx-import-source
* https://oxc.rs/docs/guide/usage/transformer/jsx.html#import-source
* @default 'react'
*/
jsxImportSource?: string
Expand Down Expand Up @@ -124,7 +123,6 @@ export default function viteReact(opts: Options = {}): Plugin[] {
const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`
const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`

const isRolldownVite = 'rolldownVersion' in vite
let runningInVite = false
let isProduction = true
let projectRoot = process.cwd()
Expand All @@ -136,72 +134,45 @@ export default function viteReact(opts: Options = {}): Plugin[] {
| undefined
let staticBabelOptions: ReactBabelOptions | undefined

// Support patterns like:
// - import * as React from 'react';
// - import React from 'react';
// - import React, {useEffect} from 'react';
const importReactRE = /\bimport\s+(?:\*\s+as\s+)?React\b/

const viteBabel: Plugin = {
name: 'vite:react-babel',
enforce: 'pre',
config(_userConfig, { command }) {
if ('rolldownVersion' in vite) {
if (opts.jsxRuntime === 'classic') {
return {
oxc: {
jsx: {
runtime: 'classic',
refresh: command === 'serve',
// disable __self and __source injection even in dev
// as this plugin injects them by babel and oxc will throw
// if development is enabled and those properties are already present
development: false,
},
jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude),
},
}
} else {
return {
oxc: {
jsx: {
runtime: 'automatic',
importSource: opts.jsxImportSource,
refresh: command === 'serve',
},
jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude),
},
optimizeDeps: {
rolldownOptions: { transform: { jsx: { runtime: 'automatic' } } },
},
}
}
}

if (opts.jsxRuntime === 'classic') {
return {
esbuild: {
jsx: 'transform',
oxc: {
jsx: {
runtime: 'classic',
refresh: command === 'serve',
// disable __self and __source injection even in dev
// as this plugin injects them by babel and oxc will throw
// if development is enabled and those properties are already present
development: false,
},
jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude),
},
}
} else {
return {
esbuild: {
jsx: 'automatic',
// keep undefined by default so that vite's esbuild transform can prioritize jsxImportSource from tsconfig
jsxImportSource: opts.jsxImportSource,
oxc: {
jsx: {
runtime: 'automatic',
importSource: opts.jsxImportSource,
refresh: command === 'serve',
},
jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude),
},
optimizeDeps: {
rolldownOptions: { transform: { jsx: { runtime: 'automatic' } } },
},
optimizeDeps: { esbuildOptions: { jsx: 'automatic' } },
}
}
},
configResolved(config) {
runningInVite = true
base = config.base
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- use ts-ignore for ecosystem-ci
// @ts-ignore only available in newer rolldown-vite
if (config.experimental.bundledDev) {
isBundledDev = true
}
Expand All @@ -227,7 +198,6 @@ export default function viteReact(opts: Options = {}): Plugin[] {
staticBabelOptions = createBabelOptions(opts.babel)

if (
(isRolldownVite || skipFastRefresh) &&
canSkipBabel(staticBabelOptions.plugins, staticBabelOptions) &&
(opts.jsxRuntime === 'classic' ? isProduction : true)
) {
Expand All @@ -237,11 +207,7 @@ export default function viteReact(opts: Options = {}): Plugin[] {
},
options(options) {
if (!runningInVite) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- use ts-ignore for ecosystem-ci
// @ts-ignore Rolldown has `transform.jsx`
options.transform ??= {}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- use ts-ignore for ecosystem-ci
// @ts-ignore Rolldown has `transform.jsx`
options.transform.jsx = {
runtime: opts.jsxRuntime,
importSource: opts.jsxImportSource,
Expand Down Expand Up @@ -292,20 +258,6 @@ export default function viteReact(opts: Options = {}): Plugin[] {
}

const isJSX = filepath.endsWith('x')
const useFastRefresh =
!(isRolldownVite || skipFastRefresh) &&
!ssr &&
(isJSX ||
(opts.jsxRuntime === 'classic'
? importReactRE.test(code)
: code.includes(jsxImportDevRuntime) ||
code.includes(jsxImportRuntime)))
if (useFastRefresh) {
plugins.push([
await loadPlugin('react-refresh/babel'),
{ skipEnvCheck: true },
])
}

if (opts.jsxRuntime === 'classic' && isJSX) {
if (!isProduction) {
Expand Down Expand Up @@ -361,22 +313,12 @@ export default function viteReact(opts: Options = {}): Plugin[] {
})

if (result) {
if (!useFastRefresh) {
return { code: result.code!, map: result.map }
}
const code = addRefreshWrapper(
result.code!,
'@vitejs/plugin-react',
id,
opts.reactRefreshHost,
)
return { code: code ?? result.code!, map: result.map }
return { code: result.code!, map: result.map }
}
},
},
}

// for rolldown-vite
const viteRefreshWrapper: Plugin = {
name: 'vite:react:refresh-wrapper',
apply: 'serve',
Expand All @@ -385,64 +327,16 @@ export default function viteReact(opts: Options = {}): Plugin[] {
return false
}

let nativePlugin: ((options: any) => Plugin) | undefined
try {
// NOTE: `+` is to bypass lint & typecheck. vite/internal exists for newer rolldown-vite
const vite = 'vite'
nativePlugin = (await import(vite + '/internal'))
.reactRefreshWrapperPlugin
} catch {}
if (
!nativePlugin ||
['7.1.10', '7.1.11', '7.1.12'].includes(vite.version)
) {
// the native plugin in 7.1.10 and 7.1.11 and 7.1.12 does not support dev properly
return true
}

delete viteRefreshWrapper.transform

return nativePlugin({
return reactRefreshWrapperPlugin({
cwd: process.cwd(),
include: makeIdFiltersToMatchWithQuery(include),
exclude: makeIdFiltersToMatchWithQuery(exclude),
jsxImportSource,
reactRefreshHost: opts.reactRefreshHost ?? '',
}) as unknown as boolean
},
// we can remove this transform hook when we drop support for rolldown-vite 7.1.12 and below
transform: {
filter: {
id: {
include: makeIdFiltersToMatchWithQuery(include),
exclude: makeIdFiltersToMatchWithQuery(exclude),
},
},
handler(code, id, options) {
const ssr = options?.ssr === true

const [filepath] = id.split('?')
const isJSX = filepath.endsWith('x')
const useFastRefresh =
!skipFastRefresh &&
!ssr &&
(isJSX ||
code.includes(jsxImportDevRuntime) ||
code.includes(jsxImportRuntime))
if (!useFastRefresh) return

const newCode = addRefreshWrapper(
code,
'@vitejs/plugin-react',
id,
opts.reactRefreshHost,
)
return newCode ? { code: newCode, map: null } : undefined
},
},
}

// for rolldown-vite
const viteConfigPost: Plugin = {
name: 'vite:react:config-post',
enforce: 'post',
Expand All @@ -454,13 +348,12 @@ export default function viteReact(opts: Options = {}): Plugin[] {
refresh: false,
},
},
// oxc option is only available in rolldown-vite
} as any
}
}
},
}

// for rolldown-vite + full bundle mode
// for full bundle mode
const viteReactRefreshBundledDevMode: Plugin = {
name: 'vite:react-refresh-fbm',
enforce: 'pre',
Expand Down Expand Up @@ -538,9 +431,9 @@ export default function viteReact(opts: Options = {}): Plugin[] {

return [
viteBabel,
...(isRolldownVite
? [viteRefreshWrapper, viteConfigPost, viteReactRefreshBundledDevMode]
: []),
viteRefreshWrapper,
viteConfigPost,
viteReactRefreshBundledDevMode,
viteReactRefresh,
virtualPreamblePlugin({
name: '@vitejs/plugin-react/preamble',
Expand Down
Loading
Loading