Skip to content

fsModuleCache 5.0.0+ ​

  • Type: boolean
  • Default: true
  • CLI: --fsModuleCache, --fsModuleCache=false

In watch mode, Vitest caches all transformed files in memory, which makes reruns fast. However, this cache is discarded once the test run finishes. This option allows Vitest to persist the transformed modules on the file system, so they can be reused across reruns and separate Vitest processes.

A single cache directory is shared by every project in the workspace. By default it lives in node_modules at the workspace root (so it is naturally invalidated when dependencies are reinstalled); use fsModuleCachePath to change its location. You can delete the cache by running vitest --clearCache.

If the config and the CLI do not set this option, Vitest reads it from the VITEST_FS_MODULE_CACHE environment variable. Set it to false to disable the cache without changing the project:

shell
VITEST_FS_MODULE_CACHE=false vitest

BROWSER SUPPORT

At the moment, this option does not affect the browser.

You can debug if your modules are cached by running vitest with a DEBUG=vitest:cache:fs environment variable:

shell
DEBUG=vitest:cache:fs vitest --fsModuleCache

TIP

The location of the cache is a single, workspace-wide directory. See fsModuleCachePath to move it.

Manifest ​

After every test run, each project writes a _manifest-<project>-<hash>.json file into the cache directory, next to the cached modules. <project> is the project name, or the name of the project's root folder if the project has no name. The manifest is grouped by Vite environment. modules maps the URL of every cached module to the name of its cache file in that directory. externalized maps the URL of every externalized dependency to the file that Node imports without a transform:

node_modules/.vitest-cache/_manifest-app-1a2b3c4d.json
json
{
  "name": "",
  "root": "/projects/app",
  "modules": {
    "ssr": {
      "/src/math.test.ts": "3b1af86df9d029d4281e7ae6ef10059153a80e14",
      "/src/math.ts": "e8e20f586e230bde9b163dfc191f4440b241272a"
    }
  },
  "externalized": {
    "ssr": {
      "/node_modules/lodash-es/lodash.js": "/projects/app/node_modules/lodash-es/lodash.js"
    }
  }
}

The manifest keeps the entries from previous runs, so a run that imports only some files does not remove the others.

A cache file contains the code that Vitest runs, so you can edit it to debug a transform. Vitest runs the edited code until the module is transformed again: when the source file or the configuration changes, or when the cache is cleared with --clearCache. Keep the //# vitestCache= comment at the end of the file, otherwise Vitest transforms the module again.

Known Issues ​

Vitest creates a persistent file hash based on file content, its id, Vite's environment configuration and coverage status. Vitest tries to use as much information as it has about the configuration, but it is still incomplete. At the moment, it is not possible to track your plugin options because there is no standard interface for it.

If you have a plugin that relies on things outside the file content or the public configuration (like reading another file or a folder), it's possible that the cache will get stale. To work around that, you can define a cache key generator to specify a dynamic option or to opt out of caching for that module:

vitest.config.js
js
import { defineConfig } from 'vitest/config'

export default defineConfig({
  plugins: [
    {
      name: 'vitest-cache',
      configureVitest({ defineCacheKeyGenerator }) {
        defineCacheKeyGenerator(({ id, sourceCode }) => {
          // never cache this id
          if (id.includes('do-not-cache')) {
            return false
          }

          // cache this file based on the value of a dynamic variable
          if (sourceCode.includes('myDynamicVar')) {
            return process.env.DYNAMIC_VAR_VALUE
          }
        })
      }
    }
  ],
  test: {
    fsModuleCache: true,
  },
})

If you are a plugin author, consider defining a cache key generator in your plugin if it can be registered with different options that affect the transform result.

On the other hand, if your plugin should not affect the cache key, you can opt out by setting api.vitest.ignoreFsModuleCache to true:

vitest.config.js
js
import { defineConfig } from 'vitest/config'

export default defineConfig({
  plugins: [
    {
      name: 'vitest-cache',
      api: {
        vitest: {
          ignoreFsModuleCache: true,
        },
      },
    },
  ],
  test: {
    fsModuleCache: true,
  },
})

Note that you can still define the cache key generator even if the plugin opts out of module caching.