Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable experimentalOptimizer #3413

Merged
merged 6 commits into from Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 2 additions & 5 deletions docs/config/index.md
Expand Up @@ -113,19 +113,16 @@ 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:

- 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.

Expand Down
9 changes: 6 additions & 3 deletions packages/vitest/src/node/error.ts
Expand Up @@ -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`)))
Expand Down
69 changes: 27 additions & 42 deletions 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'
Expand Down Expand Up @@ -134,49 +136,32 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t
}

const optimizeConfig: Partial<ViteConfig> = {}
// 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
Expand Down
31 changes: 31 additions & 0 deletions 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'
Expand Down Expand Up @@ -116,6 +118,35 @@ export function WorkspaceVitestPlugin(project: WorkspaceProject, options: Worksp
}
}

const optimizeConfig: Partial<ViteConfig> = {}
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) {
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/types/config.ts
Expand Up @@ -74,7 +74,7 @@ interface DepsOptions {
/**
* Enable dependency optimization. This can improve the performance of your tests.
*/
experimentalOptimizer?: Omit<DepOptimizationConfig, 'disabled'> & {
experimentalOptimizer?: Omit<DepOptimizationConfig, 'disabled' | 'noDiscovery'> & {
enabled: boolean
}
/**
Expand Down
9 changes: 6 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.