Skip to content

Commit 10d48bb

Browse files
authored
fix(optimizer): discover correct jsx runtime during scan (vitejs#20495)
1 parent 73b052e commit 10d48bb

File tree

7 files changed

+96
-3
lines changed

7 files changed

+96
-3
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
;(globalThis as any).__test_scan_jsx_runtime ??= 0
2+
;(globalThis as any).__test_scan_jsx_runtime++
3+
4+
export default <div />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import * as vue from 'vue'
2+
3+
export default vue
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"jsx": "react-jsx",
4+
"jsxImportSource": "vue",
5+
"strict": true,
6+
"verbatimModuleSyntax": true,
7+
"noEmit": true,
8+
"moduleResolution": "Bundler",
9+
"module": "ESNext",
10+
"target": "ESNext",
11+
"lib": ["ESNext", "DOM", "DOM.Iterable"]
12+
}
13+
}

packages/vite/src/node/__tests__/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"dependencies": {
66
"@vitejs/parent": "link:./packages/parent",
77
"@vitejs/cjs-ssr-dep": "link:./fixtures/cjs-ssr-dep",
8-
"@vitejs/test-dep-conditions": "file:./fixtures/test-dep-conditions"
8+
"@vitejs/test-dep-conditions": "file:./fixtures/test-dep-conditions",
9+
"vue": "^3.5.18"
910
}
1011
}

packages/vite/src/node/__tests__/scan.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import path from 'node:path'
12
import { describe, expect, test } from 'vitest'
23
import { commentRE, importsRE, scriptRE } from '../optimizer/scan'
34
import { multilineCommentsRE, singlelineCommentsRE } from '../utils'
5+
import { createServer, createServerModuleRunner } from '..'
46

57
describe('optimizer-scan:script-test', () => {
68
const scriptContent = `import { defineComponent } from 'vue'
@@ -123,3 +125,46 @@ describe('optimizer-scan:script-test', () => {
123125
expect(ret).not.toContain('export default')
124126
})
125127
})
128+
129+
test('scan jsx-runtime', async (ctx) => {
130+
const server = await createServer({
131+
configFile: false,
132+
logLevel: 'error',
133+
root: path.join(import.meta.dirname, 'fixtures', 'scan-jsx-runtime'),
134+
environments: {
135+
client: {
136+
// silence client optimizer
137+
optimizeDeps: {
138+
noDiscovery: true,
139+
},
140+
},
141+
ssr: {
142+
resolve: {
143+
noExternal: true,
144+
},
145+
optimizeDeps: {
146+
force: true,
147+
noDiscovery: false,
148+
entries: ['./entry-jsx.tsx', './entry-no-jsx.js'],
149+
},
150+
},
151+
},
152+
})
153+
154+
// start server to ensure optimizer run
155+
await server.listen()
156+
ctx.onTestFinished(() => server.close())
157+
158+
const runner = createServerModuleRunner(server.environments.ssr, {
159+
hmr: { logger: false },
160+
})
161+
162+
// flush initial optimizer by importing any file
163+
await runner.import('./entry-no-jsx.js')
164+
165+
// verify jsx won't trigger optimizer re-run
166+
const mod1 = await runner.import('./entry-jsx.js')
167+
const mod2 = await runner.import('./entry-jsx.js')
168+
expect((globalThis as any).__test_scan_jsx_runtime).toBe(1)
169+
expect(mod1).toBe(mod2)
170+
})

packages/vite/src/node/optimizer/scan.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,31 @@ async function prepareEsbuildScanner(
294294
const { tsconfig } = await loadTsconfigJsonForFile(
295295
path.join(environment.config.root, '_dummy.js'),
296296
)
297-
if (tsconfig.compilerOptions?.experimentalDecorators) {
298-
tsconfigRaw = { compilerOptions: { experimentalDecorators: true } }
297+
if (
298+
tsconfig.compilerOptions?.experimentalDecorators ||
299+
tsconfig.compilerOptions?.jsx ||
300+
tsconfig.compilerOptions?.jsxFactory ||
301+
tsconfig.compilerOptions?.jsxFragmentFactory ||
302+
tsconfig.compilerOptions?.jsxImportSource
303+
) {
304+
tsconfigRaw = {
305+
compilerOptions: {
306+
experimentalDecorators:
307+
tsconfig.compilerOptions?.experimentalDecorators,
308+
// esbuild uses tsconfig fields when both the normal options and tsconfig was set
309+
// but we want to prioritize the normal options
310+
jsx: esbuildOptions.jsx ? undefined : tsconfig.compilerOptions?.jsx,
311+
jsxFactory: esbuildOptions.jsxFactory
312+
? undefined
313+
: tsconfig.compilerOptions?.jsxFactory,
314+
jsxFragmentFactory: esbuildOptions.jsxFragment
315+
? undefined
316+
: tsconfig.compilerOptions?.jsxFragmentFactory,
317+
jsxImportSource: esbuildOptions.jsxImportSource
318+
? undefined
319+
: tsconfig.compilerOptions?.jsxImportSource,
320+
},
321+
}
299322
}
300323
}
301324

@@ -310,6 +333,7 @@ async function prepareEsbuildScanner(
310333
format: 'esm',
311334
logLevel: 'silent',
312335
plugins: [...plugins, plugin],
336+
jsxDev: !environment.config.isProduction,
313337
...esbuildOptions,
314338
tsconfigRaw,
315339
})

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)