Improving Vitest Performance
Tags: vitest, javascript, performance, testing
Published: 2023-05-11 13:01:00

The following is a summary of the Vitest GitHub issue ["Vitest runs tests 3x slower than Jest"](https://github.com/vitest-dev/vitest/issues/579), which if printed would require about 24 pages. So I've summed up all the ideas and advice I found there into a more concise list of things you can try if you notice Vitest being slow. Please note, many performance improvements were merged into Vitest since that issue was created so not all recommendations on this page are still relevant, the goal is just to put them in one spot in a quick, concise, easy to try list.

If you'd like to see some real world benchmarks on a 5.5 year old production app, [read my follow up post](https://dev.to/thejaredwilcurt/vitest-vs-jest-benchmarks-on-a-5-year-old-real-work-spa-4mf1) and what happened when I tried to apply some of these following techniques.


# Summary

**Things within your control to improve performance:**

* Upgrade Node.js. Newer Node versions are faster.
* Switching from `jsdom` to `happy-dom` is faster in most cases, though will require tweaking/adjusting some tests. (some note it is 3x faster to import per test)
* Remove or mock heavy dependencies (rather than importing them).
* Rather than import a dependency from a "[barrel file](https://flaming.codes/posts/barrel-files-in-javascript)", import it from a pre-built file, or directly from the actual file. **Example:**
  * Instead of `import { OneIcon } from 'thousands-of-icons';` do `import OneIcon from 'thousands-of-icons/icons/OneIcon.vue';`. This way you don't have to wait for 2,000+ icon components to be loaded and transformed on every test.
* Read up on [deps.experimentalOptimizer](https://vitest.dev/config/#deps-experimentaloptimizer) and how to adjust your include/exclude/entries settings for better performance in tests and how your dependencies are bundled during test runs.
* Instead of inlining a dependency, alias it to point to a pre-built/CJS version. Example:
   ```diff
    environment: 'happydom',
   -deps: {
   -  inline: ['element-plus']
   -}
   +alias: [
   +  {
   +    find: /^element-plus$/,
   +    replacement: resolve(__dirname, 'node_modules', 'element-plus/dist/index.full.mjs')
   +  }
   +]
   ```
* You can try `--no-threads` CLI argument, depending on your tests this may be much slower or slightly faster. Also some tests may need to be tweaked to work with this. It will use `child_process` instead of worker threads.
* The `--single-thread` CLI may also make things much slower or maybe slightly faster depending on the codebase.
* Set `css: false` to skip CSS imports in tests (If you are using `--browser` then maybe you don't want this, but also `--browser` is slower too because... it involves a real browser)
* Set `useAtomics: true` to [synchronize threads](https://vitest.dev/config/#useatomics), might improve performance in some repos, but will cause Node to crash in older Node versions.
* Increase `concurrent: 5` to a higher value to run more tests simultaneously ([maxConcurrency](https://vitest.dev/config/#maxconcurrency)).
* Similarly you can increase `minThreads: 8` to set the [minimum number of CPU threads](https://vitest.dev/config/#minthreads) that will be used to run tests (also see: [maxThreads](https://vitest.dev/config/#maxthreads))
* If you opted in to using `--sequence.shuffle` stop using it (or override with `--sequence.shuffle=false`). Running tests in a random order is slower because Vitest can cache and sort tests running the slowest ones first which is faster overall.
* In some cases the test [reporter](https://vitest.dev/config/#reporters) can be the bottleneck, if you aren't particularly attached to the one you are using you could try a different one to see if performance improves. **Example:**
  * `vitest --reporter=tap`
* If you have any style files that contain `.module` in the file name (ex: `sidebar.module.sass`). Follow [these instructions](https://github.com/vitest-dev/vitest/issues/579#issuecomment-1197227773)
* Turning [isolation](https://vitest.dev/config/#isolate) off (`--no-isolate` or `--isolate=false`) is 3-8x faster, but will likely break your existing tests, requiring them to be re-written. Also it **will** cause issues in watch mode. Generally not a good idea.
* Adjust the [slowTestThreshold](https://vitest.dev/config/#slowtestthreshold) to be bigger. If it doesn't report it as being slow, then who's to say it isn't fast? Ride that placebo.


**Information:**

* You can use the [benchmark](https://vitest.dev/config/#benchmark) feature to evaluate where time is spent during test running. Either when running a specific `test()` (as `bench()`), or by running `--bench` CLI or using `benchmark: {}` in the `test: {}` config. This can help with debugging slow tests.
* There is a `--ui` [module graph](https://vitest.dev/guide/ui.html) that may be useful when debugging performance.
* Vitest inherits settings from your dev and build Vite config. Some settings will give you better performance once you build your app, but worse performance when running tests, so you need to override these settings in the test config. (*I think*, this isn't super clear in the docs).


**The future**

* Vitest relies on the `vm` module. It is being ran in a way that is much slower than how Jest does it. If Vitest were to switch to Jest's approach it would introduce all the bugs Jest has into Vitest. So this will likely never happen as Vitest values correctness over performance (be happy that this is the case). However, once `vm` has proper native ESM support, it will be considerably faster (this is a major bottleneck for Vitest).
* If [ShadowRealms](https://github.com/tc39/proposal-shadowrealm) are ever added to EcmaScript (and implemented into V8/Node) they'll allow for a different approach to isolating code that would be faster without the downsides of sharing `global`.


* * *


Be sure to look at the follow up post for real world benchmarks on a 5 year old frontend web app.

* https://dev.to/thejaredwilcurt/vitest-vs-jest-benchmarks-on-a-5-year-old-real-work-spa-4mf1


* * *


**Photo Credits:**

"Man running along seashore during golden hour" by [Swapnil Dwivedi](https://unsplash.com/photos/Xcmfp0gBukI)