Skip to content

Commit f09299c

Browse files
authored
fix(plugin-react): apply manual runtime interop (#8546)
1 parent d641860 commit f09299c

File tree

8 files changed

+61
-25
lines changed

8 files changed

+61
-25
lines changed

packages/plugin-react/package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@
4545
"@babel/plugin-transform-react-jsx-self": "^7.17.12",
4646
"@babel/plugin-transform-react-jsx-source": "^7.16.7",
4747
"@rollup/pluginutils": "^4.2.1",
48-
"react-refresh": "^0.13.0",
49-
"resolve": "^1.22.0"
48+
"react-refresh": "^0.13.0"
5049
},
5150
"peerDependencies": {
5251
"vite": "^3.0.0-alpha"

packages/plugin-react/src/index.ts

+34-21
Original file line numberDiff line numberDiff line change
@@ -361,40 +361,53 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
361361
}
362362
}
363363

364-
// const runtimeId = 'react/jsx-runtime'
364+
const reactJsxRuntimeId = 'react/jsx-runtime'
365+
const reactJsxDevRuntimeId = 'react/jsx-dev-runtime'
366+
const virtualReactJsxRuntimeId = '\0' + reactJsxRuntimeId
367+
const virtualReactJsxDevRuntimeId = '\0' + reactJsxDevRuntimeId
365368
// Adapted from https://github.com/alloc/vite-react-jsx
366369
const viteReactJsx: Plugin = {
367370
name: 'vite:react-jsx',
368371
enforce: 'pre',
369372
config() {
370373
return {
371374
optimizeDeps: {
372-
include: ['react/jsx-dev-runtime']
375+
include: [reactJsxRuntimeId, reactJsxDevRuntimeId]
373376
}
374377
}
375-
}
376-
// TODO: this optimization may not be necesary and it is breacking esbuild+rollup compat,
377-
// see https://github.com/vitejs/vite/pull/7246#discussion_r861552185
378-
// We could still do the same trick and resolve to the optimized dependency here
379-
/*
380-
resolveId(id: string) {
381-
return id === runtimeId ? id : null
382378
},
383-
load(id: string) {
384-
if (id === runtimeId) {
385-
const runtimePath = resolve.sync(runtimeId, {
386-
basedir: projectRoot
387-
})
388-
const exports = ['jsx', 'jsxs', 'Fragment']
379+
resolveId(id, importer) {
380+
// Resolve runtime to a virtual path to be interoped.
381+
// Since the interop code re-imports `id`, we need to prevent re-resolving
382+
// to the virtual id if the importer is already the virtual id.
383+
if (id === reactJsxRuntimeId && importer !== virtualReactJsxRuntimeId) {
384+
return virtualReactJsxRuntimeId
385+
}
386+
if (
387+
id === reactJsxDevRuntimeId &&
388+
importer !== virtualReactJsxDevRuntimeId
389+
) {
390+
return virtualReactJsxDevRuntimeId
391+
}
392+
},
393+
load(id) {
394+
// Apply manual interop
395+
if (id === virtualReactJsxRuntimeId) {
389396
return [
390-
`import * as jsxRuntime from ${JSON.stringify(runtimePath)}`,
391-
// We can't use `export * from` or else any callsite that uses
392-
// this module will be compiled to `jsxRuntime.exports.jsx`
393-
// instead of the more concise `jsx` alias.
394-
...exports.map((name) => `export const ${name} = jsxRuntime.${name}`)
397+
`import * as jsxRuntime from ${JSON.stringify(reactJsxRuntimeId)}`,
398+
`export const Fragment = jsxRuntime.Fragment`,
399+
`export const jsx = jsxRuntime.jsx`,
400+
`export const jsxs = jsxRuntime.jsxs`
395401
].join('\n')
396402
}
397-
} */
403+
if (id === virtualReactJsxDevRuntimeId) {
404+
return [
405+
`import * as jsxRuntime from ${JSON.stringify(reactJsxDevRuntimeId)}`,
406+
`export const Fragment = jsxRuntime.Fragment`,
407+
`export const jsxDEV = jsxRuntime.jsxDEV`
408+
].join('\n')
409+
}
410+
}
398411
}
399412

400413
return [viteBabel, viteReactRefresh, useAutomaticRuntime && viteReactJsx]

playground/react/App.jsx

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState } from 'react'
22
import Dummy from './components/Dummy?qs-should-not-break-plugin-react'
3+
import Button from 'jsx-entry'
34

45
function App() {
56
const [count, setCount] = useState(0)
@@ -26,6 +27,7 @@ function App() {
2627
</header>
2728

2829
<Dummy />
30+
<Button>button</Button>
2931
</div>
3032
)
3133
}

playground/react/jsx-entry/Button.jsx

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const Button = ({ children }) => {
2+
return <button>{children}</button>
3+
}
4+
5+
export default Button
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "jsx-entry",
3+
"private": true,
4+
"version": "0.0.0",
5+
"main": "Button.jsx"
6+
}

playground/react/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"preview": "vite preview"
1010
},
1111
"dependencies": {
12+
"jsx-entry": "file:./jsx-entry",
1213
"react": "^17.0.2",
1314
"react-dom": "^17.0.2"
1415
},

playground/react/vite.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import react from '@vitejs/plugin-react'
22
import type { UserConfig } from 'vite'
33

44
const config: UserConfig = {
5+
mode: 'development',
56
plugins: [react()],
67
build: {
78
// to make tests faster

pnpm-lock.yaml

+11-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)