From 98a8f6b89613c31843ea76f18af591e45cacd9ee Mon Sep 17 00:00:00 2001 From: semimikoh Date: Tue, 28 Apr 2026 09:53:22 +0900 Subject: [PATCH 1/2] fix(optimizer): pass oxc jsx options to transformSync in scan The `doTransformGlobImport` function in the dependency scanner was calling `transformSync` without passing user-configured OXC transform options. This caused custom JSX settings (e.g. importSource, pragma, runtime) to be ignored during scan, resulting in incorrect dependency resolution such as attempting to resolve `react/jsx-runtime` instead of the configured custom JSX runtime. Fix #22340 --- .../entry-glob-custom-oxc.tsx | 3 ++ .../fixtures/scan-jsx-runtime/pages/index.tsx | 1 + packages/vite/src/node/__tests__/scan.spec.ts | 35 +++++++++++++++++++ packages/vite/src/node/optimizer/scan.ts | 23 +++++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/entry-glob-custom-oxc.tsx create mode 100644 packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/pages/index.tsx diff --git a/packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/entry-glob-custom-oxc.tsx b/packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/entry-glob-custom-oxc.tsx new file mode 100644 index 00000000000000..178cb0b9e87bff --- /dev/null +++ b/packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/entry-glob-custom-oxc.tsx @@ -0,0 +1,3 @@ +export const pages = import.meta.glob('./pages/*.tsx') + +export default
diff --git a/packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/pages/index.tsx b/packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/pages/index.tsx new file mode 100644 index 00000000000000..1bdcfef72ff16e --- /dev/null +++ b/packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/pages/index.tsx @@ -0,0 +1 @@ +export default
diff --git a/packages/vite/src/node/__tests__/scan.spec.ts b/packages/vite/src/node/__tests__/scan.spec.ts index b79930393913d3..6d93f91cfdd468 100644 --- a/packages/vite/src/node/__tests__/scan.spec.ts +++ b/packages/vite/src/node/__tests__/scan.spec.ts @@ -175,6 +175,41 @@ test('scan jsx-runtime', async (ctx) => { expect(mod1).toBe(mod2) }) +test('scan import.meta.glob respects oxc jsx options', async (ctx) => { + const server = await createServer({ + configFile: false, + logLevel: 'error', + root: path.join(import.meta.dirname, 'fixtures', 'scan-jsx-runtime'), + oxc: { + jsx: { + runtime: 'automatic', + importSource: 'vue', + }, + }, + optimizeDeps: { + force: true, + noDiscovery: false, + entries: ['./entry-glob-custom-oxc.tsx'], + }, + }) + ctx.onTestFinished(() => server.close()) + + const { cancel, result } = scanImports( + devToScanEnvironment(server.environments.client), + ) + ctx.onTestFinished(cancel) + + const scanResult = await result + + expect(scanResult).toMatchObject({ + deps: { + 'vue/jsx-dev-runtime': expect.any(String), + }, + missing: {}, + }) + expect(scanResult.deps).not.toHaveProperty('react/jsx-runtime') +}) + test('scan import.meta.glob package imports patterns', async (ctx) => { const server = await createServer({ configFile: false, diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index be05905a77c54c..b26b4db4868061 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -3,6 +3,7 @@ import fsp from 'node:fs/promises' import path from 'node:path' import { performance } from 'node:perf_hooks' import { scan } from 'rolldown/experimental' +import type { TransformOptions as OxcTransformOptions } from 'rolldown/utils' import { transformSync } from 'rolldown/utils' import type { PartialResolvedId, Plugin } from 'rolldown' import colors from 'picocolors' @@ -36,7 +37,7 @@ import { BaseEnvironment } from '../baseEnvironment' import type { DevEnvironment } from '../server/environment' import { transformGlobImport } from '../plugins/importMetaGlob' import { cleanUrl } from '../../shared/utils' -import { getRollupJsxPresets } from '../plugins/oxc' +import { type OxcOptions, getRollupJsxPresets } from '../plugins/oxc' export class ScanEnvironment extends BaseEnvironment { mode = 'scan' as const @@ -328,6 +329,25 @@ async function globEntries( type Loader = 'js' | 'ts' | 'jsx' | 'tsx' +function getOxcTransformOptions( + options: OxcOptions | false, +): OxcTransformOptions { + if (!options) { + return {} + } + + const { + jsxInject: _jsxInject, + include: _include, + exclude: _exclude, + jsxRefreshInclude: _jsxRefreshInclude, + jsxRefreshExclude: _jsxRefreshExclude, + ...transformOptions + } = options + + return transformOptions +} + export const scriptRE: RegExp = /(=\s]+))?)*\s*>)(.*?)<\/script>/gis export const commentRE: RegExp = //gs @@ -397,6 +417,7 @@ function rolldownScanPlugin( // transpile because `transformGlobImport` only expects js if (loader !== 'js') { const result = transformSync(id, contents, { + ...getOxcTransformOptions(environment.config.oxc), lang: loader, tsconfig: false, }) From 444340d1351fbd08e1a788d5f308caed18f38b4d Mon Sep 17 00:00:00 2001 From: semimikoh Date: Fri, 15 May 2026 08:57:11 +0900 Subject: [PATCH 2/2] fix(optimizer): use rolldown jsx options for scan glob transform --- packages/vite/src/node/__tests__/scan.spec.ts | 12 +++++- packages/vite/src/node/optimizer/scan.ts | 40 ++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/vite/src/node/__tests__/scan.spec.ts b/packages/vite/src/node/__tests__/scan.spec.ts index 6d93f91cfdd468..6658425dd5dd96 100644 --- a/packages/vite/src/node/__tests__/scan.spec.ts +++ b/packages/vite/src/node/__tests__/scan.spec.ts @@ -175,7 +175,7 @@ test('scan jsx-runtime', async (ctx) => { expect(mod1).toBe(mod2) }) -test('scan import.meta.glob respects oxc jsx options', async (ctx) => { +test('scan import.meta.glob respects rolldown transform jsx options', async (ctx) => { const server = await createServer({ configFile: false, logLevel: 'error', @@ -183,13 +183,21 @@ test('scan import.meta.glob respects oxc jsx options', async (ctx) => { oxc: { jsx: { runtime: 'automatic', - importSource: 'vue', + importSource: 'react', }, }, optimizeDeps: { force: true, noDiscovery: false, entries: ['./entry-glob-custom-oxc.tsx'], + rolldownOptions: { + transform: { + jsx: { + runtime: 'automatic', + importSource: 'vue', + }, + }, + }, }, }) ctx.onTestFinished(() => server.close()) diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index b26b4db4868061..06af7aaaecbf48 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -37,7 +37,7 @@ import { BaseEnvironment } from '../baseEnvironment' import type { DevEnvironment } from '../server/environment' import { transformGlobImport } from '../plugins/importMetaGlob' import { cleanUrl } from '../../shared/utils' -import { type OxcOptions, getRollupJsxPresets } from '../plugins/oxc' +import { getRollupJsxPresets } from '../plugins/oxc' export class ScanEnvironment extends BaseEnvironment { mode = 'scan' as const @@ -253,9 +253,6 @@ async function prepareRolldownScanner( const { plugins: pluginsFromConfig = [], ...rolldownOptions } = environment.config.optimizeDeps.rolldownOptions ?? {} - const plugins = await asyncFlatten(arraify(pluginsFromConfig)) - plugins.push(...rolldownScanPlugin(environment, deps, missing, entries)) - const transformOptions = deepClone(rolldownOptions.transform) ?? {} if (transformOptions.jsx === undefined) { transformOptions.jsx = {} @@ -268,6 +265,19 @@ async function prepareRolldownScanner( if (typeof transformOptions.jsx === 'object') { transformOptions.jsx.development ??= !environment.config.isProduction } + const transformSyncJsxOptions: OxcTransformOptions['jsx'] = + transformOptions.jsx === false ? undefined : transformOptions.jsx + + const plugins = await asyncFlatten(arraify(pluginsFromConfig)) + plugins.push( + ...rolldownScanPlugin( + environment, + deps, + missing, + entries, + transformSyncJsxOptions, + ), + ) async function build() { await scan({ @@ -329,25 +339,6 @@ async function globEntries( type Loader = 'js' | 'ts' | 'jsx' | 'tsx' -function getOxcTransformOptions( - options: OxcOptions | false, -): OxcTransformOptions { - if (!options) { - return {} - } - - const { - jsxInject: _jsxInject, - include: _include, - exclude: _exclude, - jsxRefreshInclude: _jsxRefreshInclude, - jsxRefreshExclude: _jsxRefreshExclude, - ...transformOptions - } = options - - return transformOptions -} - export const scriptRE: RegExp = /(=\s]+))?)*\s*>)(.*?)<\/script>/gis export const commentRE: RegExp = //gs @@ -363,6 +354,7 @@ function rolldownScanPlugin( depImports: Record, missing: Record, entries: string[], + jsxOptions: OxcTransformOptions['jsx'], ): Plugin[] { const seen = new Map() async function resolveId( @@ -417,7 +409,7 @@ function rolldownScanPlugin( // transpile because `transformGlobImport` only expects js if (loader !== 'js') { const result = transformSync(id, contents, { - ...getOxcTransformOptions(environment.config.oxc), + ...(jsxOptions !== undefined ? { jsx: jsxOptions } : {}), lang: loader, tsconfig: false, })