diff --git a/docs/config/index.md b/docs/config/index.md index 6f8e92213767..107463f96463 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -113,10 +113,6 @@ Handling for dependencies resolution. - **Version:** Since Vitest 0.29.0 - **See also:** [Dep Optimization Options](https://vitejs.dev/config/dep-optimization-options.html) -::: warning -This feature is temporarily disabled since Vitest 0.30.0. -::: - Enable dependency optimization. If you have a lot of tests, this might improve their performance. For `jsdom` and `happy-dom` environments, when Vitest will encounter the external library, it will be bundled into a single file using esbuild and imported as a whole module. This is good for several reasons: @@ -124,8 +120,9 @@ For `jsdom` and `happy-dom` environments, when Vitest will encounter the externa - Importing packages with a lot of imports is expensive. By bundling them into one file we can save a lot of time - Importing UI libraries is expensive because they are not meant to run inside Node.js - Your `alias` configuration is now respected inside bundled packages +- Code in your tests is running closer to how it's running in the browser -You can opt-out of this behavior for certain packages with `exclude` option. You can read more about available options in [Vite](https://vitejs.dev/config/dep-optimization-options.html) docs. +Be aware that only packages in `deps.experimentalOptimizer.include` option are bundled (some plugins populate this automatically, like Svelte). You can read more about available options in [Vite](https://vitejs.dev/config/dep-optimization-options.html) docs. This options also inherits your `optimizeDeps` configuration. If you redefine `include`/`exclude`/`entries` option in `deps.experimentalOptimizer` it will overwrite your `optimizeDeps` when running tests. diff --git a/packages/vitest/src/node/error.ts b/packages/vitest/src/node/error.ts index e6e9114e63e2..5b3584cf20e6 100644 --- a/packages/vitest/src/node/error.ts +++ b/packages/vitest/src/node/error.ts @@ -169,9 +169,12 @@ function printModuleWarningForPackage(logger: Logger, path: string, name: string + c.green(`export default { test: { deps: { - inline: [ - ${c.yellow(c.bold(`"${name}"`))} - ] + experimentalOptimizer: { + enabled: true, + include: [ + ${c.yellow(c.bold(`"${name}"`))} + ] + } } } }\n`))) diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index da177f7bca6f..47defea31662 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -1,3 +1,5 @@ +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' @@ -134,49 +136,32 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t } const optimizeConfig: Partial = {} - // TODO: optimizer is temporary disabled, until Vite provides "optimzier.byDefault" option - // const optimizer = preOptions.deps?.experimentalOptimizer - // if (!optimizer?.enabled) { - optimizeConfig.cacheDir = undefined - optimizeConfig.optimizeDeps = { - // experimental in Vite >2.9.2, entries remains to help with older versions - disabled: true, - entries: [], + 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' + 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'), + } } - // } - // else { - // const root = config.root || process.cwd() - // // TODO: add support for experimental optimizer - // const entries = [] - // // const [...entries] = await ctx.globAllTestFiles(preOptions as ResolvedConfig, preOptions.dir || root) - // if (preOptions?.setupFiles) { - // const setupFiles = toArray(preOptions.setupFiles).map((file: string) => - // normalize( - // resolveModule(file, { paths: [root] }) - // ?? resolve(root, file), - // ), - // ) - // entries.push(...setupFiles) - // } - // const cacheDir = preOptions.cache !== false ? preOptions.cache?.dir : null - // optimizeConfig.cacheDir = cacheDir ?? 'node_modules/.vitest' - // optimizeConfig.optimizeDeps = { - // ...viteConfig.optimizeDeps, - // ...optimizer, - // disabled: false, - // entries: [...(viteConfig.optimizeDeps?.entries || []), ...entries], - // exclude: ['vitest', ...builtinModules, ...(optimizer.exclude || viteConfig.optimizeDeps?.exclude || [])], - // include: (optimizer.include || viteConfig.optimizeDeps?.include || []).filter((n: string) => n !== 'vitest'), - // } - // // Vite throws an error that it cannot rename "deps_temp", but optimization still works - // // let's not show this error to users - // const { error: logError } = console - // console.error = (...args) => { - // if (typeof args[0] === 'string' && args[0].includes('/deps_temp')) - // return - // return logError(...args) - // } - // } Object.assign(config, optimizeConfig) return config diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index bef905d8a90c..91aebe65b8d5 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -1,5 +1,7 @@ +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' @@ -116,6 +118,35 @@ 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'), + } + } + Object.assign(config, optimizeConfig) + return config }, async configureServer(server) { diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts index e8e9b2f064ff..0a18bca805a6 100644 --- a/packages/vitest/src/types/config.ts +++ b/packages/vitest/src/types/config.ts @@ -74,7 +74,7 @@ interface DepsOptions { /** * Enable dependency optimization. This can improve the performance of your tests. */ - experimentalOptimizer?: Omit & { + experimentalOptimizer?: Omit & { enabled: boolean } /** diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 64ea153b44d9..a65e911d3eaa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9202,7 +9202,7 @@ packages: '@vue/compiler-core': 3.3.4 '@vue/compiler-dom': 3.3.4 '@vue/compiler-sfc': 3.3.4 - '@vue/reactivity': 3.3.4 + '@vue/reactivity': 3.2.47 '@vue/shared': 3.3.4 dev: true @@ -18811,6 +18811,7 @@ packages: pathe: 1.1.0 pkg-types: 1.0.3 ufo: 1.1.2 + dev: true /modern-node-polyfills@0.1.3(rollup@3.20.2): resolution: {integrity: sha512-/4dB85Sdkt9MjWwtpKnsNTYhh0+fqjFC4ZEgDP4B0e6kyzbGUnX4NDxTUCaVwRLVF9gcEDcRQjol8pn05B3TUQ==} @@ -20047,7 +20048,7 @@ packages: resolution: {integrity: sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==} dependencies: jsonc-parser: 3.2.0 - mlly: 1.3.0 + mlly: 1.2.0 pathe: 1.1.0 /pkg-types@1.0.3: @@ -20056,6 +20057,7 @@ packages: jsonc-parser: 3.2.0 mlly: 1.2.0 pathe: 1.1.0 + dev: true /playwright-chromium@1.30.0: resolution: {integrity: sha512-ZfqjYdFuxnZxK02mDZtHFK/Mi0+cjCVn51RmwLwLLHA8PkCExk0odmZH2REx+LjqX8tDLGnmf6vDnPAirdSY0g==} @@ -23330,6 +23332,7 @@ packages: /ufo@1.1.2: resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} + dev: true /uglify-js@3.17.0: resolution: {integrity: sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==} @@ -23440,7 +23443,7 @@ packages: fast-glob: 3.2.12 local-pkg: 0.4.3 magic-string: 0.30.0 - mlly: 1.3.0 + mlly: 1.2.0 pathe: 1.1.0 pkg-types: 1.0.3 scule: 1.0.0