diff --git a/packages/vitest/src/node/create.ts b/packages/vitest/src/node/create.ts index e254af4456f3..e69286eec2a3 100644 --- a/packages/vitest/src/node/create.ts +++ b/packages/vitest/src/node/create.ts @@ -28,7 +28,7 @@ export async function createVitest(mode: VitestRunMode, options: UserConfig, vit const server = await createServer(mergeConfig(config, mergeConfig(viteOverrides, { root: options.root }))) // optimizer needs .listen() to be called - if (ctx.config.api?.port || ctx.config.deps?.experimentalOptimizer?.enabled) + if (ctx.config.api?.port || ctx.config.deps?.experimentalOptimizer?.web?.enabled || ctx.config.deps?.experimentalOptimizer?.ssr?.enabled) await server.listen() else await server.pluginContainer.buildStart({}) diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index aa6a7053a0cc..77abab12969d 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -1,5 +1,3 @@ -import { builtinModules } from 'node:module' -import { version as viteVersion } from 'vite' import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite' import { relative } from 'pathe' import { configDefaults } from '../../defaults' @@ -14,6 +12,7 @@ import { GlobalSetupPlugin } from './globalSetup' import { CSSEnablerPlugin } from './cssEnabler' import { CoverageTransform } from './coverageTransform' import { MocksPlugin } from './mocks' +import { resolveOptimizerConfig } from './utils' export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('test')): Promise { const userConfig = deepMerge({}, options) as UserConfig @@ -42,13 +41,13 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t // preliminary merge of options to be able to create server options for vite // however to allow vitest plugins to modify vitest config values // this is repeated in configResolved where the config is final - const preOptions = deepMerge( + const testConfig = deepMerge( {} as UserConfig, configDefaults, options, removeUndefinedValues(viteConfig.test ?? {}), ) - preOptions.api = resolveApiServerConfig(preOptions) + testConfig.api = resolveApiServerConfig(testConfig) if (viteConfig.define) { delete viteConfig.define['import.meta.vitest'] @@ -90,8 +89,8 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t let open: string | boolean | undefined - if (preOptions.ui && preOptions.open) - open = preOptions.uiBase ?? '/__vitest__/' + if (testConfig.ui && testConfig.open) + open = testConfig.uiBase ?? '/__vitest__/' const config: ViteConfig = { root: viteConfig.test?.root || options.root, @@ -105,16 +104,16 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t // by default Vite resolves `module` field, which not always a native ESM module // setting this option can bypass that and fallback to cjs version mainFields: [], - alias: preOptions.alias, + alias: testConfig.alias, conditions: ['node'], // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error // @ts-ignore we support Vite ^3.0, but browserField is available in Vite ^3.2 browserField: false, }, server: { - ...preOptions.api, + ...testConfig.api, watch: { - ignored: preOptions.watchExclude, + ignored: testConfig.watchExclude, }, open, hmr: false, @@ -122,7 +121,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t }, } - const classNameStrategy = (typeof preOptions.css !== 'boolean' && preOptions.css?.modules?.classNameStrategy) || 'stable' + const classNameStrategy = (typeof testConfig.css !== 'boolean' && testConfig.css?.modules?.classNameStrategy) || 'stable' if (classNameStrategy !== 'scoped') { config.css ??= {} @@ -135,45 +134,14 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t } } - const optimizeConfig: Partial = {} - const optimizer = preOptions.deps?.experimentalOptimizer - const [major, minor] = viteVersion.split('.').map(Number) - const allowed = major >= 5 || (major === 4 && minor >= 3) - if (!allowed && optimizer?.enabled === true) - console.warn(`Vitest: "deps.experimentalOptimizer" is only available in Vite >= 4.3.0, current Vite version: ${viteVersion}`) - if (!allowed || optimizer?.enabled !== true) { - optimizeConfig.cacheDir = undefined - optimizeConfig.optimizeDeps = { - // experimental in Vite >2.9.2, entries remains to help with older versions - disabled: true, - entries: [], - } - } - else { - const cacheDir = preOptions.cache !== false ? preOptions.cache?.dir : null - optimizeConfig.cacheDir = cacheDir ?? 'node_modules/.vitest' - const exclude = [ - 'vitest', - ...builtinModules, - ...optimizer.exclude || [], - ...viteConfig.optimizeDeps?.exclude || [], - ] - const include = [ - ...optimizer.include || [], - ...viteConfig.optimizeDeps?.include || [], - ].filter((n: string) => !exclude.includes(n)) - - optimizeConfig.optimizeDeps = { - ...viteConfig.optimizeDeps, - ...optimizer, - noDiscovery: true, - disabled: false, - entries: [], - exclude, - include, - } + const webOptimizer = resolveOptimizerConfig(testConfig.deps?.experimentalOptimizer?.web, viteConfig.optimizeDeps, testConfig) + const ssrOptimizer = resolveOptimizerConfig(testConfig.deps?.experimentalOptimizer?.ssr, viteConfig.ssr?.optimizeDeps, testConfig) + + config.cacheDir = webOptimizer.cacheDir || ssrOptimizer.cacheDir || config.cacheDir + config.optimizeDeps = webOptimizer.optimizeDeps + config.ssr = { + optimizeDeps: ssrOptimizer.optimizeDeps, } - Object.assign(config, optimizeConfig) return config }, diff --git a/packages/vitest/src/node/plugins/utils.ts b/packages/vitest/src/node/plugins/utils.ts new file mode 100644 index 000000000000..9d1e93f86abe --- /dev/null +++ b/packages/vitest/src/node/plugins/utils.ts @@ -0,0 +1,34 @@ +import { builtinModules } from 'node:module' +import { version as viteVersion } from 'vite' +import type { DepOptimizationOptions } from 'vite' +import type { DepsOptimizationOptions, InlineConfig } from '../../types' + +export function resolveOptimizerConfig(testOptionc: DepsOptimizationOptions | undefined, viteOptions: DepOptimizationOptions | undefined, testConfig: InlineConfig) { + const newConfig: { cacheDir?: string; optimizeDeps: DepOptimizationOptions } = {} as any + const [major, minor] = viteVersion.split('.').map(Number) + const allowed = major >= 5 || (major === 4 && minor >= 3) + if (!allowed && testOptionc?.enabled === true) + console.warn(`Vitest: "deps.optimizer" is only available in Vite >= 4.3.0, current Vite version: ${viteVersion}`) + if (!allowed || testOptionc?.enabled !== true) { + newConfig.cacheDir = undefined + newConfig.optimizeDeps = { + // experimental in Vite >2.9.2, entries remains to help with older versions + disabled: true, + entries: [], + } + } + else { + const cacheDir = testConfig.cache !== false ? testConfig.cache?.dir : null + newConfig.cacheDir = cacheDir ?? 'node_modules/.vitest' + newConfig.optimizeDeps = { + ...viteOptions, + ...testOptionc, + noDiscovery: true, + disabled: false, + entries: [], + exclude: ['vitest', ...builtinModules, ...(testOptionc.exclude || viteOptions?.exclude || [])], + include: (testOptionc.include || viteOptions?.include || []).filter((n: string) => n !== 'vitest'), + } + } + return newConfig +} diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index 91aebe65b8d5..2901443a9052 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -1,7 +1,5 @@ -import { builtinModules } from 'node:module' import { dirname, relative } from 'pathe' import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite' -import { version as viteVersion } from 'vite' import { configDefaults } from '../../defaults' import { generateScopedClassName } from '../../integrations/css/css-modules' import { deepMerge } from '../../utils/base' @@ -12,6 +10,7 @@ import { CSSEnablerPlugin } from './cssEnabler' import { EnvReplacerPlugin } from './envReplacer' import { GlobalSetupPlugin } from './globalSetup' import { MocksPlugin } from './mocks' +import { resolveOptimizerConfig } from './utils' interface WorkspaceOptions extends UserWorkspaceConfig { root?: string @@ -118,34 +117,14 @@ export function WorkspaceVitestPlugin(project: WorkspaceProject, options: Worksp } } - const optimizeConfig: Partial = {} - const optimizer = testConfig.deps?.experimentalOptimizer - const [major, minor] = viteVersion.split('.').map(Number) - const allowed = major >= 5 || (major === 4 && minor >= 3) - if (!allowed && optimizer?.enabled === true) - console.warn(`Vitest: "deps.experimentalOptimizer" is only available in Vite >= 4.3.0, current Vite version: ${viteVersion}`) - if (!allowed || optimizer?.enabled !== true) { - optimizeConfig.cacheDir = undefined - optimizeConfig.optimizeDeps = { - // experimental in Vite >2.9.2, entries remains to help with older versions - disabled: true, - entries: [], - } - } - else { - const cacheDir = testConfig.cache !== false ? testConfig.cache?.dir : null - optimizeConfig.cacheDir = cacheDir ?? 'node_modules/.vitest' - optimizeConfig.optimizeDeps = { - ...viteConfig.optimizeDeps, - ...optimizer, - noDiscovery: true, - disabled: false, - entries: [], - exclude: ['vitest', ...builtinModules, ...(optimizer.exclude || viteConfig.optimizeDeps?.exclude || [])], - include: (optimizer.include || viteConfig.optimizeDeps?.include || []).filter((n: string) => n !== 'vitest'), - } + const webOptimizer = resolveOptimizerConfig(testConfig.deps?.experimentalOptimizer?.web, viteConfig.optimizeDeps, testConfig) + const ssrOptimizer = resolveOptimizerConfig(testConfig.deps?.experimentalOptimizer?.ssr, viteConfig.ssr?.optimizeDeps, testConfig) + + config.cacheDir = webOptimizer.cacheDir || ssrOptimizer.cacheDir || config.cacheDir + config.optimizeDeps = webOptimizer.optimizeDeps + config.ssr = { + optimizeDeps: ssrOptimizer.optimizeDeps, } - Object.assign(config, optimizeConfig) return config }, diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index 1c67ef4ea95f..d123d71e339b 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -52,7 +52,7 @@ export async function initializeProject(workspacePath: string | number, ctx: Vit const server = await createServer(config) // optimizer needs .listen() to be called - if (ctx.config.api?.port || project.config.deps?.experimentalOptimizer?.enabled) + if (ctx.config.api?.port || project.config.deps?.experimentalOptimizer?.web?.enabled || project.config.deps?.experimentalOptimizer?.ssr?.enabled) await server.listen() else await server.pluginContainer.buildStart({}) @@ -269,8 +269,13 @@ export class WorkspaceProject { reporters: [], deps: { ...this.config.deps, - experimentalOptimizer: { - enabled: this.config.deps?.experimentalOptimizer?.enabled ?? false, + optimizer: { + web: { + enabled: this.config.deps?.experimentalOptimizer?.web?.enabled ?? false, + }, + ssr: { + enabled: this.config.deps?.experimentalOptimizer?.ssr?.enabled ?? false, + }, }, }, snapshotOptions: { diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts index 0a18bca805a6..8bdaaa495840 100644 --- a/packages/vitest/src/types/config.ts +++ b/packages/vitest/src/types/config.ts @@ -70,12 +70,17 @@ interface SequenceOptions { hooks?: SequenceHooks } +export type DepsOptimizationOptions = Omit & { + enabled: boolean +} + interface DepsOptions { /** * Enable dependency optimization. This can improve the performance of your tests. */ - experimentalOptimizer?: Omit & { - enabled: boolean + experimentalOptimizer?: { + web?: DepsOptimizationOptions + ssr?: DepsOptimizationOptions } /** * Externalize means that Vite will bypass the package to native Node. diff --git a/packages/vitest/src/utils/base.ts b/packages/vitest/src/utils/base.ts index 86e3713143f1..aa111023d85c 100644 --- a/packages/vitest/src/utils/base.ts +++ b/packages/vitest/src/utils/base.ts @@ -129,7 +129,7 @@ export function stdout(): NodeJS.WriteStream { } export function getEnvironmentTransformMode(config: ResolvedConfig, environment: VitestEnvironment) { - if (!config.deps?.experimentalOptimizer?.enabled) + if (!config.deps?.experimentalOptimizer?.ssr?.enabled && !config.deps?.experimentalOptimizer?.web?.enabled) return undefined return (environment === 'happy-dom' || environment === 'jsdom') ? 'web' : 'ssr' }