Skip to content

Vite is a fast build tool and dev server for modern web apps. In a Vite monorepo, Nx runs and caches Vite tasks across every project so you only rebuild what changed.

The @nx/vite plugin adds inferred tasks and project configuration generators.

You can use Vite with Nx without the plugin and still get task caching, task orchestration, and the project graph.

The @nx/vite plugin supports the following package versions.

PackageSupported Versions
vite^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0

For supported vitest versions, see the @nx/vitest plugin requirements.

Nx generators install the latest supported versions automatically when scaffolding new projects.

Install the plugin:

Terminal window
nx add @nx/vite

Configure an existing project to use Vite:

Terminal window
nx g @nx/vite:configuration --project=my-app

Verify inferred tasks in the project details view:

Terminal window
nx show project my-app --web

Replace my-app with your project name.

Use a framework preset and keep the setup minimal:

Terminal window
npx create-nx-workspace@latest --preset=react-standalone --bundler=vite

For the full framework workflows, see the React introduction or Web app reference.

  • nx dev my-app starts the Vite dev server for the project (same as the deprecated serve target).
  • nx build my-app creates a production build in dist/ (controlled by build.outDir in vite.config.*) and registers the outputs for Nx caching.
  • nx preview my-app serves the production build using Vite preview (runs after build).
  • nx serve-static my-app serves the built assets from dist/ for quick smoke tests.
  • nx typecheck my-app runs TypeScript typechecking. @nx/js/typescript infers this task, except for Vue projects, which get a vue-tsc task from @nx/vite/plugin.

Replace my-app with your project name.

The @nx/vite plugin infers tasks by reading Vite config files. Any of the following config files will be picked up:

  • vite.config.js
  • vite.config.ts
  • vite.config.mjs
  • vite.config.mts
  • vite.config.cjs
  • vite.config.cts

The configuration directory must also contain a package.json or project.json.

Build tasks are only created when the project is buildable. A project is treated as buildable when any of the following are true:

  • build.lib is set in vite.config.*
  • build.rollupOptions.input or build.rolldownOptions.input is set (Vite 8 uses rolldownOptions)
  • builder.buildApp is set
  • an index.html file exists at the project root

Dev, preview, and serve-static tasks are created for buildable projects. If you are in library mode (build.lib), these tasks are skipped unless you explicitly configure a dev server (e.g. server.host or server.port).

Typecheck tasks are only created for Vue projects that have a tsconfig*.json file, and they run vue-tsc. Other projects get their typecheck task from @nx/js/typescript, which the @nx/vite:init generator registers when it's missing.

Configure @nx/vite/plugin in the plugins array in nx.json:

nx.json
{
"plugins": [
{
"plugin": "@nx/vite/plugin",
"options": {
"buildTargetName": "build",
"previewTargetName": "preview",
"serveTargetName": "serve",
"devTargetName": "dev",
"serveStaticTargetName": "serve-static",
"typecheckTargetName": "typecheck",
"buildDepsTargetName": "build-deps",
"watchDepsTargetName": "watch-deps"
}
}
]
}

serveTargetName is deprecated; use devTargetName instead. buildDepsTargetName and watchDepsTargetName create tasks that build or watch project dependencies.

OptionDescriptionDefault
buildTargetNameName of the Vite build taskbuild
previewTargetNameName of the Vite preview taskpreview
serveTargetNameName of the deprecated Vite serve taskserve
devTargetNameName of the Vite dev server taskdev
serveStaticTargetNameName of the static file server taskserve-static
typecheckTargetNameName of the Vue vue-tsc typecheck task, or false to skip ittypecheck
compilerVue typecheck compiler: vue-tsc, tsc, or tsgoauto-detected
buildDepsTargetNameName of the build-deps task for dependency buildsnone
watchDepsTargetNameName of the watch-deps task for dependency watchesnone

The build and typecheck tasks are cached, with build outputs based on your Vite configuration. The dev, preview, and static-server tasks are continuous. When compiler is omitted, Nx uses vue-tsc when it detects a Vite Vue plugin. Set compiler to tsc or tsgo to drop the vue-tsc task and let @nx/js/typescript provide typecheck instead. To typecheck with tsgo, set compiler: 'tsgo' on @nx/js/typescript, which ignores the Vite plugin's compiler.

The inferred dev and preview targets come with a readyWhen check, so a task can wait until the server accepts requests instead of only until it has started. The nxReadySignal() plugin reports the dev or preview server's address to Nx once it listens. Generated app configs include it, and nx migrate adds it to existing application configs when you update to Nx 24. In any other config, import it from @nx/vite/plugins/nx-ready-signal.plugin and add it to plugins in vite.config.*. The report carries the address the server actually listens on, so the waiting task tests against it however the port was chosen.

Without the plugin, the check resolves the Vite config when the task runs instead, in the task's environment and with its options. That covers .env files and the --port, --host, and --mode (-m) flags. It takes the port from the --port flag, server.port or preview.port, or the Vite defaults of 5173 and 4173, and waits for it. With a port of 0, the server picks its own port. There's nothing to wait for then, and the target counts as ready once it has started. If another process holds the configured port and Vite moves to the next free one, this check can pass before the server is up. The serve-static target's file server reports its address once it listens.

A dependent task starts as soon as the server task has started, unless its dependsOn entry sets waitFor to ready:

apps/myapp-e2e/project.json
{
"targets": {
"e2e": {
"dependsOn": [
{ "projects": "myapp", "target": "dev", "waitFor": "ready" }
]
}
}
}

The waiting task gets the server's address in the NX_READY_URL environment variable, when exactly one target it waits for reported one. A readyWhen on the target in targetDefaults or in the project configuration replaces the inferred check, and null turns it off. For the other checks, see wait for a continuous task to be ready. For signaling from your own server, see signal readiness from the task.

To stop inference for a specific project, exclude its config file with include/exclude filters in nx.json:

nx.json
{
"plugins": [
{
"plugin": "@nx/vite/plugin",
"exclude": ["apps/legacy/**"]
}
]
}

To avoid specific targets, adjust the config files that trigger them. For example, use library mode (build.lib) to skip dev, preview, and serve-static unless you set dev server options.

To see what tasks Nx inferred for a project, open the project details view in Nx Console or run:

Terminal window
nx show project my-app --web

A target defaults plugin filter for these tasks must use the exact identifier @nx/vite/plugin.

In CI, Nx runs nx affected to rebuild and retest only the projects a change touches, and caches results to skip repeated work.

For a complete pipeline, see Set up CI.