diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 6ded98de8f1da9..62e99d4d7baa85 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -338,9 +338,9 @@ function normalizeOxcResolverResult( export function oxcResolvePlugin( resolveOptions: ResolvePluginOptionsWithOverrides, -): [RolldownPlugin, RolldownPlugin, RolldownPlugin, Plugin] { +): (RolldownPlugin | Plugin)[] { return [ - devOnlyResolvePlugin(resolveOptions), + ...(!resolveOptions.isBuild ? [devOnlyResolvePlugin(resolveOptions)] : []), importGlobSubpathImportsResolvePlugin(resolveOptions), createBuiltinPluginWithEnvironmentSupport( 'vite:resolve-builtin', @@ -368,72 +368,85 @@ export function oxcResolvePlugin( }) }, ), - createBuiltinPluginWithEnvironmentSupport('vite:resolve', (environment) => { - // The resolve plugin is used for createIdResolver and the depsOptimizer should be - // disabled in that case, so deps optimization is opt-in when creating the plugin. - const depsOptimizer = - resolveOptions.optimizeDeps && environment.mode === 'dev' - ? environment.depsOptimizer - : undefined - const options: InternalResolveOptions = { - ...environment.config.resolve, - ...resolveOptions, // plugin options + resolve options overrides - } - - return oxcResolveBuiltinPlugin({ - environmentName: environment.name, - environmentConsumer: environment.config.consumer, - resolveOptions: options, - finalizeBareSpecifier: !depsOptimizer - ? undefined - : (resolvedId, rawId, importer) => { - // if we reach here, it's a valid dep import that hasn't been optimized. - const isJsType = isOptimizable(resolvedId, depsOptimizer.options) - const exclude = depsOptimizer?.options.exclude - - // check for deep import, e.g. "my-lib/foo" - const deepMatch = deepImportRE.exec(rawId) - // package name doesn't include postfixes - // trim them to support importing package with queries (e.g. `import css from 'normalize.css?inline'`) - const pkgId = deepMatch - ? deepMatch[1] || deepMatch[2] - : cleanUrl(rawId) - - const skipOptimization = - depsOptimizer.options.noDiscovery || - !isJsType || - (importer && isInNodeModules(importer)) || - exclude?.includes(pkgId) || - exclude?.includes(rawId) || - SPECIAL_QUERY_RE.test(resolvedId) - - let newId = resolvedId - if (skipOptimization) { - // excluded from optimization - // Inject a version query to npm deps so that the browser - // can cache it without re-validation, but only do so for known js types. - // otherwise we may introduce duplicated modules for externalized files - // from pre-bundled deps. - const versionHash = depsOptimizer!.metadata.browserHash - if (versionHash && isJsType) { - newId = injectQuery(newId, `v=${versionHash}`) - } - } else { - // this is a missing import, queue optimize-deps re-run and - // get a resolved its optimized info - const optimizedInfo = depsOptimizer!.registerMissingImport( - rawId, - newId, - ) - newId = depsOptimizer!.getOptimizedDepId(optimizedInfo) + ...(resolveOptions.isBuild + ? [] + : [ + createBuiltinPluginWithEnvironmentSupport( + 'vite:resolve', + (environment) => { + // The resolve plugin is used for createIdResolver and the depsOptimizer should be + // disabled in that case, so deps optimization is opt-in when creating the plugin. + const depsOptimizer = + resolveOptions.optimizeDeps && environment.mode === 'dev' + ? environment.depsOptimizer + : undefined + const options: InternalResolveOptions = { + ...environment.config.resolve, + ...resolveOptions, // plugin options + resolve options overrides } - return newId + + return oxcResolveBuiltinPlugin({ + environmentName: environment.name, + environmentConsumer: environment.config.consumer, + resolveOptions: options, + finalizeBareSpecifier: !depsOptimizer + ? undefined + : (resolvedId, rawId, importer) => { + // if we reach here, it's a valid dep import that hasn't been optimized. + const isJsType = isOptimizable( + resolvedId, + depsOptimizer.options, + ) + const exclude = depsOptimizer?.options.exclude + + // check for deep import, e.g. "my-lib/foo" + const deepMatch = deepImportRE.exec(rawId) + // package name doesn't include postfixes + // trim them to support importing package with queries (e.g. `import css from 'normalize.css?inline'`) + const pkgId = deepMatch + ? deepMatch[1] || deepMatch[2] + : cleanUrl(rawId) + + const skipOptimization = + depsOptimizer.options.noDiscovery || + !isJsType || + (importer && isInNodeModules(importer)) || + exclude?.includes(pkgId) || + exclude?.includes(rawId) || + SPECIAL_QUERY_RE.test(resolvedId) + + let newId = resolvedId + if (skipOptimization) { + // excluded from optimization + // Inject a version query to npm deps so that the browser + // can cache it without re-validation, but only do so for known js types. + // otherwise we may introduce duplicated modules for externalized files + // from pre-bundled deps. + const versionHash = depsOptimizer!.metadata.browserHash + if (versionHash && isJsType) { + newId = injectQuery(newId, `v=${versionHash}`) + } + } else { + // this is a missing import, queue optimize-deps re-run and + // get a resolved its optimized info + const optimizedInfo = + depsOptimizer!.registerMissingImport(rawId, newId) + newId = depsOptimizer!.getOptimizedDepId(optimizedInfo) + } + return newId + }, + finalizeOtherSpecifiers(resolvedId, rawId) { + return ensureVersionQuery( + resolvedId, + rawId, + options, + depsOptimizer, + ) + }, + }) }, - finalizeOtherSpecifiers(resolvedId, rawId) { - return ensureVersionQuery(resolvedId, rawId, options, depsOptimizer) - }, - }) - }), + ), + ]), ] } @@ -444,11 +457,6 @@ function devOnlyResolvePlugin( return { name: 'vite:resolve-dev', - ...({ - apply(_, env) { - return env.command === 'serve' - }, - } satisfies Partial), resolveId: { filter: { id: { @@ -608,8 +616,6 @@ function oxcResolveBuiltinPlugin({ return { name: 'vite:resolve', - apply: 'serve', - resolveId(id, importer, resolveOpts) { if ( id[0] === '\0' ||