Wβ
All docs
π
Sign Up/Sign In
vite.dev/guide
Public Link
Apr 16, 2025, 7:46:41 AM - complete - 157.9 kB
Apr 16, 2025, 7:46:41 AM - complete - 157.9 kB
Apr 6, 2025, 10:07:50 AM - complete - 156.8 kB
Starting URLs:
https://vite.dev/guide
CSS Selector:
main
Max Pages:
2000
Exclude Patterns:
https://vite.dev/guide/api
https://vite.dev/guide/philosophy.html
https://vite.dev/guide/why.html
https://vite.dev/guide/migration.html
https://vite.dev/changes/
## Page: https://vite.dev/guide # Getting Started β ## Overview β Vite (French word for "quick", pronounced `/vit/`, like "veet") is a build tool that aims to provide a faster and leaner development experience for modern web projects. It consists of two major parts: * A dev server that provides rich feature enhancements over native ES modules, for example extremely fast Hot Module Replacement (HMR). * A build command that bundles your code with Rollup, pre-configured to output highly optimized static assets for production. Vite is opinionated and comes with sensible defaults out of the box. Read about what's possible in the Features Guide. Support for frameworks or integration with other tools is possible through Plugins. The Config Section explains how to adapt Vite to your project if needed. Vite is also highly extensible via its Plugin API and JavaScript API with full typing support. You can learn more about the rationale behind the project in the Why Vite section. ## Browser Support β During development, Vite sets `esnext` as the transform target, because we assume a modern browser is used and it supports all of the latest JavaScript and CSS features. This prevents syntax lowering, letting Vite serve modules as close as possible to the original source code. For the production build, by default Vite targets browsers that support modern JavaScript, such as native ES Modules, native ESM dynamic import, `import.meta`, nullish coalescing, and BigInt. Legacy browsers can be supported via the official @vitejs/plugin-legacy. See the Building for Production section for more details. ## Trying Vite Online β You can try Vite online on StackBlitz. It runs the Vite-based build setup directly in the browser, so it is almost identical to the local setup but doesn't require installing anything on your machine. You can navigate to `vite.new/{template}` to select which framework to use. The supported template presets are: | JavaScript | TypeScript | | --- | --- | | vanilla | vanilla-ts | | vue | vue-ts | | react | react-ts | | preact | preact-ts | | lit | lit-ts | | svelte | svelte-ts | | solid | solid-ts | | qwik | qwik-ts | ## Scaffolding Your First Vite Project β Compatibility Note Vite requires Node.js version 18+ or 20+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it. npmYarnpnpmBun bash $ npm create vite@latest bash $ yarn create vite bash $ pnpm create vite bash $ bun create vite Then follow the prompts! You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: npmYarnpnpmBun bash # npm 7+, extra double-dash is needed: $ npm create vite@latest my-vue-app -- --template vue bash $ yarn create vite my-vue-app --template vue bash $ pnpm create vite my-vue-app --template vue bash $ bun create vite my-vue-app --template vue See create-vite for more details on each supported template: `vanilla`, `vanilla-ts`, `vue`, `vue-ts`, `react`, `react-ts`, `react-swc`, `react-swc-ts`, `preact`, `preact-ts`, `lit`, `lit-ts`, `svelte`, `svelte-ts`, `solid`, `solid-ts`, `qwik`, `qwik-ts`. You can use `.` for the project name to scaffold in the current directory. ## Community Templates β create-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for community maintained templates that include other tools or target different frameworks. For a template at `https://github.com/user/project`, you can try it out online using `https://github.stackblitz.com/user/project` (adding `.stackblitz` after `github` to the URL of the project). You can also use a tool like degit to scaffold your project with one of the templates. Assuming the project is on GitHub and uses `main` as the default branch, you can create a local copy using: bash npx degit user/project#main my-project cd my-project npm install npm run dev ## Manual Installation β In your project, you can install the `vite` CLI using: npmYarnpnpmBun bash $ npm install -D vite bash $ yarn add -D vite bash $ pnpm add -D vite bash $ bun add -D vite And create an `index.html` file like this: html <p>Hello Vite!</p> Then run the appropriate CLI command in your terminal: npmYarnpnpmBun bash $ npx vite bash $ yarn vite bash $ pnpm vite bash $ bunx vite The `index.html` will be served on `http://localhost:5173`. ## `index.html` and Project Root β One thing you may have noticed is that in a Vite project, `index.html` is front-and-central instead of being tucked away inside `public`. This is intentional: during development Vite is a server, and `index.html` is the entry point to your application. Vite treats `index.html` as source code and part of the module graph. It resolves `<script type="module" src="...">` that references your JavaScript source code. Even inline `<script type="module">` and CSS referenced via `<link href>` also enjoy Vite-specific features. In addition, URLs inside `index.html` are automatically rebased so there's no need for special `%PUBLIC_URL%` placeholders. Similar to static http servers, Vite has the concept of a "root directory" which your files are served from. You will see it referenced as `<root>` throughout the rest of the docs. Absolute URLs in your source code will be resolved using the project root as base, so you can write code as if you are working with a normal static file server (except way more powerful!). Vite is also capable of handling dependencies that resolve to out-of-root file system locations, which makes it usable even in a monorepo-based setup. Vite also supports multi-page apps with multiple `.html` entry points. #### Specifying Alternative Root β Running `vite` starts the dev server using the current working directory as root. You can specify an alternative root with `vite serve some/sub/dir`. Note that Vite will also resolve its config file (i.e. `vite.config.js`) inside the project root, so you'll need to move it if the root is changed. ## Command Line Interface β In a project where Vite is installed, you can use the `vite` binary in your npm scripts, or run it directly with `npx vite`. Here are the default npm scripts in a scaffolded Vite project: package.json json { "scripts": { "dev": "vite", // start dev server, aliases: `vite dev`, `vite serve` "build": "vite build", // build for production "preview": "vite preview" // locally preview production build } } You can specify additional CLI options like `--port` or `--open`. For a full list of CLI options, run `npx vite --help` in your project. Learn more about the Command Line Interface ## Using Unreleased Commits β If you can't wait for a new release to test the latest features, you can install a specific commit of Vite with https://pkg.pr.new: npmYarnpnpmBun bash $ npm install -D https://pkg.pr.new/vite@SHA bash $ yarn add -D https://pkg.pr.new/vite@SHA bash $ pnpm add -D https://pkg.pr.new/vite@SHA bash $ bun add -D https://pkg.pr.new/vite@SHA Replace `SHA` with any of Vite's commit SHAs. Note that only commits within the last month will work, as older commit releases are purged. Alternatively, you can also clone the vite repo to your local machine and then build and link it yourself (pnpm is required): bash git clone https://github.com/vitejs/vite.git cd vite pnpm install cd packages/vite pnpm run build pnpm link --global # use your preferred package manager for this step Then go to your Vite based project and run `pnpm link --global vite` (or the package manager that you used to link `vite` globally). Now restart the development server to ride on the bleeding edge! Dependencies using Vite To replace the Vite version used by dependencies transitively, you should use npm overrides or pnpm overrides. ## Community β If you have questions or need help, reach out to the community at Discord and GitHub Discussions. --- ## Page: https://vite.dev/guide/ # Getting Started β ## Overview β Vite (French word for "quick", pronounced `/vit/`, like "veet") is a build tool that aims to provide a faster and leaner development experience for modern web projects. It consists of two major parts: * A dev server that provides rich feature enhancements over native ES modules, for example extremely fast Hot Module Replacement (HMR). * A build command that bundles your code with Rollup, pre-configured to output highly optimized static assets for production. Vite is opinionated and comes with sensible defaults out of the box. Read about what's possible in the Features Guide. Support for frameworks or integration with other tools is possible through Plugins. The Config Section explains how to adapt Vite to your project if needed. Vite is also highly extensible via its Plugin API and JavaScript API with full typing support. You can learn more about the rationale behind the project in the Why Vite section. ## Browser Support β During development, Vite sets `esnext` as the transform target, because we assume a modern browser is used and it supports all of the latest JavaScript and CSS features. This prevents syntax lowering, letting Vite serve modules as close as possible to the original source code. For the production build, by default Vite targets browsers that support modern JavaScript, such as native ES Modules, native ESM dynamic import, `import.meta`, nullish coalescing, and BigInt. Legacy browsers can be supported via the official @vitejs/plugin-legacy. See the Building for Production section for more details. ## Trying Vite Online β You can try Vite online on StackBlitz. It runs the Vite-based build setup directly in the browser, so it is almost identical to the local setup but doesn't require installing anything on your machine. You can navigate to `vite.new/{template}` to select which framework to use. The supported template presets are: | JavaScript | TypeScript | | --- | --- | | vanilla | vanilla-ts | | vue | vue-ts | | react | react-ts | | preact | preact-ts | | lit | lit-ts | | svelte | svelte-ts | | solid | solid-ts | | qwik | qwik-ts | ## Scaffolding Your First Vite Project β Compatibility Note Vite requires Node.js version 18+ or 20+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it. npmYarnpnpmBun bash $ npm create vite@latest bash $ yarn create vite bash $ pnpm create vite bash $ bun create vite Then follow the prompts! You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: npmYarnpnpmBun bash # npm 7+, extra double-dash is needed: $ npm create vite@latest my-vue-app -- --template vue bash $ yarn create vite my-vue-app --template vue bash $ pnpm create vite my-vue-app --template vue bash $ bun create vite my-vue-app --template vue See create-vite for more details on each supported template: `vanilla`, `vanilla-ts`, `vue`, `vue-ts`, `react`, `react-ts`, `react-swc`, `react-swc-ts`, `preact`, `preact-ts`, `lit`, `lit-ts`, `svelte`, `svelte-ts`, `solid`, `solid-ts`, `qwik`, `qwik-ts`. You can use `.` for the project name to scaffold in the current directory. ## Community Templates β create-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for community maintained templates that include other tools or target different frameworks. For a template at `https://github.com/user/project`, you can try it out online using `https://github.stackblitz.com/user/project` (adding `.stackblitz` after `github` to the URL of the project). You can also use a tool like degit to scaffold your project with one of the templates. Assuming the project is on GitHub and uses `main` as the default branch, you can create a local copy using: bash npx degit user/project#main my-project cd my-project npm install npm run dev ## Manual Installation β In your project, you can install the `vite` CLI using: npmYarnpnpmBun bash $ npm install -D vite bash $ yarn add -D vite bash $ pnpm add -D vite bash $ bun add -D vite And create an `index.html` file like this: html <p>Hello Vite!</p> Then run the appropriate CLI command in your terminal: npmYarnpnpmBun bash $ npx vite bash $ yarn vite bash $ pnpm vite bash $ bunx vite The `index.html` will be served on `http://localhost:5173`. ## `index.html` and Project Root β One thing you may have noticed is that in a Vite project, `index.html` is front-and-central instead of being tucked away inside `public`. This is intentional: during development Vite is a server, and `index.html` is the entry point to your application. Vite treats `index.html` as source code and part of the module graph. It resolves `<script type="module" src="...">` that references your JavaScript source code. Even inline `<script type="module">` and CSS referenced via `<link href>` also enjoy Vite-specific features. In addition, URLs inside `index.html` are automatically rebased so there's no need for special `%PUBLIC_URL%` placeholders. Similar to static http servers, Vite has the concept of a "root directory" which your files are served from. You will see it referenced as `<root>` throughout the rest of the docs. Absolute URLs in your source code will be resolved using the project root as base, so you can write code as if you are working with a normal static file server (except way more powerful!). Vite is also capable of handling dependencies that resolve to out-of-root file system locations, which makes it usable even in a monorepo-based setup. Vite also supports multi-page apps with multiple `.html` entry points. #### Specifying Alternative Root β Running `vite` starts the dev server using the current working directory as root. You can specify an alternative root with `vite serve some/sub/dir`. Note that Vite will also resolve its config file (i.e. `vite.config.js`) inside the project root, so you'll need to move it if the root is changed. ## Command Line Interface β In a project where Vite is installed, you can use the `vite` binary in your npm scripts, or run it directly with `npx vite`. Here are the default npm scripts in a scaffolded Vite project: package.json json { "scripts": { "dev": "vite", // start dev server, aliases: `vite dev`, `vite serve` "build": "vite build", // build for production "preview": "vite preview" // locally preview production build } } You can specify additional CLI options like `--port` or `--open`. For a full list of CLI options, run `npx vite --help` in your project. Learn more about the Command Line Interface ## Using Unreleased Commits β If you can't wait for a new release to test the latest features, you can install a specific commit of Vite with https://pkg.pr.new: npmYarnpnpmBun bash $ npm install -D https://pkg.pr.new/vite@SHA bash $ yarn add -D https://pkg.pr.new/vite@SHA bash $ pnpm add -D https://pkg.pr.new/vite@SHA bash $ bun add -D https://pkg.pr.new/vite@SHA Replace `SHA` with any of Vite's commit SHAs. Note that only commits within the last month will work, as older commit releases are purged. Alternatively, you can also clone the vite repo to your local machine and then build and link it yourself (pnpm is required): bash git clone https://github.com/vitejs/vite.git cd vite pnpm install cd packages/vite pnpm run build pnpm link --global # use your preferred package manager for this step Then go to your Vite based project and run `pnpm link --global vite` (or the package manager that you used to link `vite` globally). Now restart the development server to ride on the bleeding edge! Dependencies using Vite To replace the Vite version used by dependencies transitively, you should use npm overrides or pnpm overrides. ## Community β If you have questions or need help, reach out to the community at Discord and GitHub Discussions. --- ## Page: https://vite.dev/guide/philosophy # Project Philosophy β ## Lean Extendable Core β Vite doesn't intend to cover every use case for every user. Vite aims to support the most common patterns to build Web apps out-of-the-box, but Vite core must remain lean with a small API surface to keep the project maintainable long-term. This goal is possible thanks to Vite's rollup-based plugin system. Features that can be implemented as external plugins will generally not be added to Vite core. vite-plugin-pwa is a great example of what can be achieved out of Vite core, and there are a lot of well maintained plugins to cover your needs. Vite works closely with the Rollup project to ensure that plugins can be used in both plain-rollup and Vite projects as much as possible, trying to push needed extensions to the Plugin API upstream when possible. ## Pushing the Modern Web β Vite provides opinionated features that push writing modern code. For example: * The source code can only be written in ESM, where non-ESM dependencies need to be pre-bundled as ESM in order to work. * Web workers are encouraged to be written with the `new Worker` syntax to follow modern standards. * Node.js modules cannot be used in the browser. When adding new features, these patterns are followed to create a future-proof API, which may not always be compatible with other build tools. ## A Pragmatic Approach to Performance β Vite has been focused on performance since its origins. Its dev server architecture allows HMR that stays fast as projects scale. Vite uses native tools like esbuild and SWC to implement intensive tasks but keeps the rest of the code in JS to balance speed with flexibility. When needed, framework plugins will tap into Babel to compile user code. And during build time Vite currently uses Rollup where bundling size and having access to a wide ecosystem of plugins are more important than raw speed. Vite will continue to evolve internally, using new libraries as they appear to improve DX while keeping its API stable. ## Building Frameworks on Top of Vite β Although Vite can be used by users directly, it shines as a tool to create frameworks. Vite core is framework agnostic, but there are polished plugins for each UI framework. Its JS API allows App Framework authors to use Vite features to create tailored experiences for their users. Vite includes support for SSR primitives, usually present in higher-level tools but fundamental to building modern web frameworks. And Vite plugins complete the picture by offering a way to share between frameworks. Vite is also a great fit when paired with Backend frameworks like Ruby and Laravel. ## An Active Ecosystem β Vite evolution is a cooperation between framework and plugin maintainers, users, and the Vite team. We encourage active participation in Vite's Core development once a project adopts Vite. We work closely with the main projects in the ecosystem to minimize regressions on each release, aided by tools like vite-ecosystem-ci. It allows us to run the CI of major projects using Vite on selected PRs and gives us a clear status of how the Ecosystem would react to a release. We strive to fix regressions before they hit users and allow projects to update to the next versions as soon as they are released. If you are working with Vite, we invite you to join Vite's Discord and get involved in the project too. --- ## Page: https://vite.dev/guide/why # Why Vite β ## The Problems β Before ES modules were available in browsers, developers had no native mechanism for authoring JavaScript in a modularized fashion. This is why we are all familiar with the concept of "bundling": using tools that crawl, process and concatenate our source modules into files that can run in the browser. Over time we have seen tools like webpack, Rollup and Parcel, which greatly improved the development experience for frontend developers. However, as we build more and more ambitious applications, the amount of JavaScript we are dealing with is also increasing dramatically. It is not uncommon for large scale projects to contain thousands of modules. We are starting to hit a performance bottleneck for JavaScript based tooling: it can often take an unreasonably long wait (sometimes up to minutes!) to spin up a dev server, and even with Hot Module Replacement (HMR), file edits can take a couple of seconds to be reflected in the browser. The slow feedback loop can greatly affect developers' productivity and happiness. Vite aims to address these issues by leveraging new advancements in the ecosystem: the availability of native ES modules in the browser, and the rise of JavaScript tools written in compile-to-native languages. ### Slow Server Start β When cold-starting the dev server, a bundler-based build setup has to eagerly crawl and build your entire application before it can be served. Vite improves the dev server start time by first dividing the modules in an application into two categories: **dependencies** and **source code**. * **Dependencies** are mostly plain JavaScript that do not change often during development. Some large dependencies (e.g. component libraries with hundreds of modules) are also quite expensive to process. Dependencies may also be shipped in various module formats (e.g. ESM or CommonJS). Vite pre-bundles dependencies using esbuild. esbuild is written in Go and pre-bundles dependencies 10-100x faster than JavaScript-based bundlers. * **Source code** often contains non-plain JavaScript that needs transforming (e.g. JSX, CSS or Vue/Svelte components), and will be edited very often. Also, not all source code needs to be loaded at the same time (e.g. with route-based code-splitting). Vite serves source code over native ESM. This is essentially letting the browser take over part of the job of a bundler: Vite only needs to transform and serve source code on demand, as the browser requests it. Code behind conditional dynamic imports is only processed if actually used on the current screen. Bundle based dev server entry Β·Β·Β· route route module module module module Β·Β·Β· Bundle Server ready Native ESM based dev server entry Β·Β·Β· route route module module module module Β·Β·Β· Server ready Dynamic import (code split point) HTTP request ### Slow Updates β When a file is edited in a bundler-based build setup, it is inefficient to rebuild the whole bundle for an obvious reason: the update speed will degrade linearly with the size of the app. In some bundlers, the dev server runs the bundling in memory so that it only needs to invalidate part of its module graph when a file changes, but it still needs to re-construct the entire bundle and reload the web page. Reconstructing the bundle can be expensive, and reloading the page blows away the current state of the application. This is why some bundlers support Hot Module Replacement (HMR): allowing a module to "hot replace" itself without affecting the rest of the page. This greatly improves DX - however, in practice we've found that even HMR update speed deteriorates significantly as the size of the application grows. In Vite, HMR is performed over native ESM. When a file is edited, Vite only needs to precisely invalidate the chain between the edited module and its closest HMR boundary (most of the time only the module itself), making HMR updates consistently fast regardless of the size of your application. Vite also leverages HTTP headers to speed up full page reloads (again, let the browser do more work for us): source code module requests are made conditional via `304 Not Modified`, and dependency module requests are strongly cached via `Cache-Control: max-age=31536000,immutable` so they don't hit the server again once cached. Once you experience how fast Vite is, we highly doubt you'd be willing to put up with bundled development again. ## Why Bundle for Production β Even though native ESM is now widely supported, shipping unbundled ESM in production is still inefficient (even with HTTP/2) due to the additional network round trips caused by nested imports. To get the optimal loading performance in production, it is still better to bundle your code with tree-shaking, lazy-loading and common chunk splitting (for better caching). Ensuring optimal output and behavioral consistency between the dev server and the production build isn't easy. This is why Vite ships with a pre-configured build command that bakes in many performance optimizations out of the box. ## Why Not Bundle with esbuild? β While Vite leverages esbuild to pre-bundle some dependencies in dev, Vite does not use esbuild as a bundler for production builds. Vite's current plugin API isn't compatible with using `esbuild` as a bundler. In spite of `esbuild` being faster, Vite's adoption of Rollup's flexible plugin API and infrastructure heavily contributed to its success in the ecosystem. For the time being, we believe that Rollup offers a better performance-vs-flexibility tradeoff. Rollup has also been working on performance improvements, switching its parser to SWC in v4. And there is an ongoing effort to build a Rust-port of Rollup called Rolldown. Once Rolldown is ready, it could replace both Rollup and esbuild in Vite, improving build performance significantly and removing inconsistencies between development and build. You can watch Evan You's ViteConf 2023 keynote for more details. ## How Vite Relates to Other Unbundled Build Tools? β WMR by the Preact team looked to provide a similar feature set. Vite's universal Rollup plugin API for dev and build was inspired by it. WMR is no longer maintained. The Preact team now recommends Vite with @preactjs/preset-vite. Snowpack was also a no-bundle native ESM dev server, very similar in scope to Vite. Vite's dependency pre-bundling is also inspired by Snowpack v1 (now `esinstall`). Snowpack is no longer being maintained. The Snowpack team is now working on Astro, a static site builder powered by Vite. @web/dev-server (previously `es-dev-server`) is a great project and Vite 1.0's Koa-based server setup was inspired by it. The `@web` umbrella project is actively maintained and contains many other excellent tools that may benefit Vite users as well. --- ## Page: https://vite.dev/guide/features # Features β At the very basic level, developing using Vite is not that different from using a static file server. However, Vite provides many enhancements over native ESM imports to support various features that are typically seen in bundler-based setups. ## npm Dependency Resolving and Pre-Bundling β Native ES imports do not support bare module imports like the following: js import { someMethod } from 'my-dep' The above will throw an error in the browser. Vite will detect such bare module imports in all served source files and perform the following: 1. Pre-bundle them to improve page loading speed and convert CommonJS / UMD modules to ESM. The pre-bundling step is performed with esbuild and makes Vite's cold start time significantly faster than any JavaScript-based bundler. 2. Rewrite the imports to valid URLs like `/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd` so that the browser can import them properly. **Dependencies are Strongly Cached** Vite caches dependency requests via HTTP headers, so if you wish to locally edit/debug a dependency, follow the steps here. ## Hot Module Replacement β Vite provides an HMR API over native ESM. Frameworks with HMR capabilities can leverage the API to provide instant, precise updates without reloading the page or blowing away application state. Vite provides first-party HMR integrations for Vue Single File Components and React Fast Refresh. There are also official integrations for Preact via @prefresh/vite. Note you don't need to manually set these up - when you create an app via `create-vite`, the selected templates would have these pre-configured for you already. ## TypeScript β Vite supports importing `.ts` files out of the box. ### Transpile Only β Note that Vite only performs transpilation on `.ts` files and does **NOT** perform type checking. It assumes type checking is taken care of by your IDE and build process. The reason Vite does not perform type checking as part of the transform process is because the two jobs work fundamentally differently. Transpilation can work on a per-file basis and aligns perfectly with Vite's on-demand compile model. In comparison, type checking requires knowledge of the entire module graph. Shoe-horning type checking into Vite's transform pipeline will inevitably compromise Vite's speed benefits. Vite's job is to get your source modules into a form that can run in the browser as fast as possible. To that end, we recommend separating static analysis checks from Vite's transform pipeline. This principle applies to other static analysis checks such as ESLint. * For production builds, you can run `tsc --noEmit` in addition to Vite's build command. * During development, if you need more than IDE hints, we recommend running `tsc --noEmit --watch` in a separate process, or use vite-plugin-checker if you prefer having type errors directly reported in the browser. Vite uses esbuild to transpile TypeScript into JavaScript which is about 20~30x faster than vanilla `tsc`, and HMR updates can reflect in the browser in under 50ms. Use the Type-Only Imports and Export syntax to avoid potential problems like type-only imports being incorrectly bundled, for example: ts import type { T } from 'only/types' export type { T } ### TypeScript Compiler Options β Some configuration fields under `compilerOptions` in `tsconfig.json` require special attention. #### `isolatedModules` β * TypeScript documentation Should be set to `true`. It is because `esbuild` only performs transpilation without type information, it doesn't support certain features like const enum and implicit type-only imports. You must set `"isolatedModules": true` in your `tsconfig.json` under `compilerOptions`, so that TS will warn you against the features that do not work with isolated transpilation. If a dependency doesn't work well with `"isolatedModules": true`. You can use `"skipLibCheck": true` to temporarily suppress the errors until it is fixed upstream. #### `useDefineForClassFields` β * TypeScript documentation The default value will be `true` if the TypeScript target is `ES2022` or newer including `ESNext`. It is consistent with the behavior of TypeScript 4.3.2+. Other TypeScript targets will default to `false`. `true` is the standard ECMAScript runtime behavior. If you are using a library that heavily relies on class fields, please be careful about the library's intended usage of it. While most libraries expect `"useDefineForClassFields": true`, you can explicitly set `useDefineForClassFields` to `false` if your library doesn't support it. #### `target` β * TypeScript documentation Vite ignores the `target` value in the `tsconfig.json`, following the same behavior as `esbuild`. To specify the target in dev, the `esbuild.target` option can be used, which defaults to `esnext` for minimal transpilation. In builds, the `build.target` option takes higher priority over `esbuild.target` and can also be set if needed. `useDefineForClassFields` If `target` in `tsconfig.json` is not `ESNext` or `ES2022` or newer, or if there's no `tsconfig.json` file, `useDefineForClassFields` will default to `false` which can be problematic with the default `esbuild.target` value of `esnext`. It may transpile to static initialization blocks which may not be supported in your browser. As such, it is recommended to set `target` to `ESNext` or `ES2022` or newer, or set `useDefineForClassFields` to `true` explicitly when configuring `tsconfig.json`. #### Other Compiler Options Affecting the Build Result β * `extends` * `importsNotUsedAsValues` * `preserveValueImports` * `verbatimModuleSyntax` * `jsx` * `jsxFactory` * `jsxFragmentFactory` * `jsxImportSource` * `experimentalDecorators` * `alwaysStrict` `skipLibCheck` Vite starter templates have `"skipLibCheck": "true"` by default to avoid typechecking dependencies, as they may choose to only support specific versions and configurations of TypeScript. You can learn more at vuejs/vue-cli#5688. ### Client Types β Vite's default types are for its Node.js API. To shim the environment of client side code in a Vite application, add a `d.ts` declaration file: typescript /// <reference types="vite/client" /> Using `compilerOptions.types` Alternatively, you can add `vite/client` to `compilerOptions.types` inside `tsconfig.json`: tsconfig.json json { "compilerOptions": { "types": ["vite/client", "some-other-global-lib"] } } Note that if `compilerOptions.types` is specified, only these packages will be included in the global scope (instead of all visible β@typesβ packages). `vite/client` provides the following type shims: * Asset imports (e.g. importing an `.svg` file) * Types for the Vite-injected constants on `import.meta.env` * Types for the HMR API on `import.meta.hot` TIP To override the default typing, add a type definition file that contains your typings. Then, add the type reference before `vite/client`. For example, to make the default import of `*.svg` a React component: * `vite-env-override.d.ts` (the file that contains your typings): ts declare module '*.svg' { const content: React.FC<React.SVGProps<SVGElement>> export default content } * The file containing the reference to `vite/client`: ts /// <reference types="./vite-env-override.d.ts" /> /// <reference types="vite/client" /> ## HTML β HTML files stand front-and-center of a Vite project, serving as the entry points for your application, making it simple to build single-page and multi-page applications. Any HTML files in your project root can be directly accessed by its respective directory path: * `<root>/index.html` -> `http://localhost:5173/` * `<root>/about.html` -> `http://localhost:5173/about.html` * `<root>/blog/index.html` -> `http://localhost:5173/blog/index.html` Assets referenced by HTML elements such as `<script type="module" src>` and `<link href>` are processed and bundled as part of the app. The full list of supported elements are as below: * `<audio src>` * `<embed src>` * `<img src>` and `<img srcset>` * `<image src>` * `<input src>` * `<link href>` and `<link imagesrcset>` * `<object data>` * `<script type="module" src>` * `<source src>` and `<source srcset>` * `<track src>` * `<use href>` and `<use xlink:href>` * `<video src>` and `<video poster>` * `<meta content>` * Only if `name` attribute matches `msapplication-tileimage`, `msapplication-square70x70logo`, `msapplication-square150x150logo`, `msapplication-wide310x150logo`, `msapplication-square310x310logo`, `msapplication-config`, or `twitter:image` * Or only if `property` attribute matches `og:image`, `og:image:url`, `og:image:secure_url`, `og:audio`, `og:audio:secure_url`, `og:video`, or `og:video:secure_url` html <!doctype html> <html> <head> <link rel="icon" href="/favicon.ico" /> <link rel="stylesheet" href="/src/styles.css" /> </head> <body> <img src="/src/images/logo.svg" alt="logo" /> <script type="module" src="/src/main.js"></script> </body> </html> To opt-out of HTML processing on certain elements, you can add the `vite-ignore` attribute on the element, which can be useful when referencing external assets or CDN. ## Frameworks β All modern frameworks maintain integrations with Vite. Most framework plugins are maintained by each framework team, with the exception of the official Vue and React Vite plugins that are maintained in the vite org: * Vue support via @vitejs/plugin-vue * Vue JSX support via @vitejs/plugin-vue-jsx * React support via @vitejs/plugin-react * React using SWC support via @vitejs/plugin-react-swc Check out the Plugins Guide for more information. ## JSX β `.jsx` and `.tsx` files are also supported out of the box. JSX transpilation is also handled via esbuild. Your framework of choice will already configure JSX out of the box (for example, Vue users should use the official @vitejs/plugin-vue-jsx plugin, which provides Vue 3 specific features including HMR, global component resolving, directives and slots). If using JSX with your own framework, custom `jsxFactory` and `jsxFragment` can be configured using the `esbuild` option. For example, the Preact plugin would use: vite.config.js js import { defineConfig } from 'vite' export default defineConfig({ esbuild: { jsxFactory: 'h', jsxFragment: 'Fragment', }, }) More details in esbuild docs. You can inject the JSX helpers using `jsxInject` (which is a Vite-only option) to avoid manual imports: vite.config.js js import { defineConfig } from 'vite' export default defineConfig({ esbuild: { jsxInject: `import React from 'react'`, }, }) ## CSS β Importing `.css` files will inject its content to the page via a `<style>` tag with HMR support. ### `@import` Inlining and Rebasing β Vite is pre-configured to support CSS `@import` inlining via `postcss-import`. Vite aliases are also respected for CSS `@import`. In addition, all CSS `url()` references, even if the imported files are in different directories, are always automatically rebased to ensure correctness. `@import` aliases and URL rebasing are also supported for Sass and Less files (see CSS Pre-processors). ### PostCSS β If the project contains valid PostCSS config (any format supported by postcss-load-config, e.g. `postcss.config.js`), it will be automatically applied to all imported CSS. Note that CSS minification will run after PostCSS and will use `build.cssTarget` option. ### CSS Modules β Any CSS file ending with `.module.css` is considered a CSS modules file. Importing such a file will return the corresponding module object: example.module.css css .red { color: red; } js import classes from './example.module.css' document.getElementById('foo').className = classes.red CSS modules behavior can be configured via the `css.modules` option. If `css.modules.localsConvention` is set to enable camelCase locals (e.g. `localsConvention: 'camelCaseOnly'`), you can also use named imports: js // .apply-color -> applyColor import { applyColor } from './example.module.css' document.getElementById('foo').className = applyColor ### CSS Pre-processors β Because Vite targets modern browsers only, it is recommended to use native CSS variables with PostCSS plugins that implement CSSWG drafts (e.g. postcss-nesting) and author plain, future-standards-compliant CSS. That said, Vite does provide built-in support for `.scss`, `.sass`, `.less`, `.styl` and `.stylus` files. There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed: bash # .scss and .sass npm add -D sass-embedded # or sass # .less npm add -D less # .styl and .stylus npm add -D stylus If using Vue single file components, this also automatically enables `<style lang="sass">` et al. Vite improves `@import` resolving for Sass and Less so that Vite aliases are also respected. In addition, relative `url()` references inside imported Sass/Less files that are in different directories from the root file are also automatically rebased to ensure correctness. `@import` alias and url rebasing are not supported for Stylus due to its API constraints. You can also use CSS modules combined with pre-processors by prepending `.module` to the file extension, for example `style.module.scss`. ### Disabling CSS injection into the page β The automatic injection of CSS contents can be turned off via the `?inline` query parameter. In this case, the processed CSS string is returned as the module's default export as usual, but the styles aren't injected to the page. js import './foo.css' // will be injected into the page import otherStyles from './bar.css?inline' // will not be injected NOTE Default and named imports from CSS files (e.g `import style from './foo.css'`) are removed since Vite 5. Use the `?inline` query instead. ### Lightning CSS β Starting from Vite 4.4, there is experimental support for Lightning CSS. You can opt into it by adding `css.transformer: 'lightningcss'` to your config file and install the optional `lightningcss` dependency: bash npm add -D lightningcss If enabled, CSS files will be processed by Lightning CSS instead of PostCSS. To configure it, you can pass Lightning CSS options to the `css.lightningcss` config option. To configure CSS Modules, you'll use `css.lightningcss.cssModules` instead of `css.modules` (which configures the way PostCSS handles CSS modules). By default, Vite uses esbuild to minify CSS. Lightning CSS can also be used as the CSS minifier with `build.cssMinify: 'lightningcss'`. NOTE CSS Pre-processors aren't supported when using Lightning CSS. ## Static Assets β Importing a static asset will return the resolved public URL when it is served: js import imgUrl from './img.png' document.getElementById('hero-img').src = imgUrl Special queries can modify how assets are loaded: js // Explicitly load assets as URL import assetAsURL from './asset.js?url' js // Load assets as strings import assetAsString from './shader.glsl?raw' js // Load Web Workers import Worker from './worker.js?worker' js // Web Workers inlined as base64 strings at build time import InlineWorker from './worker.js?worker&inline' More details in Static Asset Handling. ## JSON β JSON files can be directly imported - named imports are also supported: js // import the entire object import json from './example.json' // import a root field as named exports - helps with tree-shaking! import { field } from './example.json' ## Glob Import β Vite supports importing multiple modules from the file system via the special `import.meta.glob` function: js const modules = import.meta.glob('./dir/*.js') The above will be transformed into the following: js // code produced by vite const modules = { './dir/bar.js': () => import('./dir/bar.js'), './dir/foo.js': () => import('./dir/foo.js'), } You can then iterate over the keys of the `modules` object to access the corresponding modules: js for (const path in modules) { modules[path]().then((mod) => { console.log(path, mod) }) } Matched files are by default lazy-loaded via dynamic import and will be split into separate chunks during build. If you'd rather import all the modules directly (e.g. relying on side-effects in these modules to be applied first), you can pass `{ eager: true }` as the second argument: js const modules = import.meta.glob('./dir/*.js', { eager: true }) The above will be transformed into the following: js // code produced by vite import * as __vite_glob_0_0 from './dir/bar.js' import * as __vite_glob_0_1 from './dir/foo.js' const modules = { './dir/bar.js': __vite_glob_0_0, './dir/foo.js': __vite_glob_0_1, } ### Multiple Patterns β The first argument can be an array of globs, for example js const modules = import.meta.glob(['./dir/*.js', './another/*.js']) ### Negative Patterns β Negative glob patterns are also supported (prefixed with `!`). To ignore some files from the result, you can add exclude glob patterns to the first argument: js const modules = import.meta.glob(['./dir/*.js', '!**/bar.js']) js // code produced by vite const modules = { './dir/foo.js': () => import('./dir/foo.js'), } #### Named Imports β It's possible to only import parts of the modules with the `import` options. ts const modules = import.meta.glob('./dir/*.js', { import: 'setup' }) ts // code produced by vite const modules = { './dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup), './dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup), } When combined with `eager` it's even possible to have tree-shaking enabled for those modules. ts const modules = import.meta.glob('./dir/*.js', { import: 'setup', eager: true, }) ts // code produced by vite: import { setup as __vite_glob_0_0 } from './dir/bar.js' import { setup as __vite_glob_0_1 } from './dir/foo.js' const modules = { './dir/bar.js': __vite_glob_0_0, './dir/foo.js': __vite_glob_0_1, } Set `import` to `default` to import the default export. ts const modules = import.meta.glob('./dir/*.js', { import: 'default', eager: true, }) ts // code produced by vite: import { default as __vite_glob_0_0 } from './dir/bar.js' import { default as __vite_glob_0_1 } from './dir/foo.js' const modules = { './dir/bar.js': __vite_glob_0_0, './dir/foo.js': __vite_glob_0_1, } #### Custom Queries β You can also use the `query` option to provide queries to imports, for example, to import assets as a string or as a url: ts const moduleStrings = import.meta.glob('./dir/*.svg', { query: '?raw', import: 'default', }) const moduleUrls = import.meta.glob('./dir/*.svg', { query: '?url', import: 'default', }) ts // code produced by vite: const moduleStrings = { './dir/bar.svg': () => import('./dir/bar.svg?raw').then((m) => m['default']), './dir/foo.svg': () => import('./dir/foo.svg?raw').then((m) => m['default']), } const moduleUrls = { './dir/bar.svg': () => import('./dir/bar.svg?url').then((m) => m['default']), './dir/foo.svg': () => import('./dir/foo.svg?url').then((m) => m['default']), } You can also provide custom queries for other plugins to consume: ts const modules = import.meta.glob('./dir/*.js', { query: { foo: 'bar', bar: true }, }) ### Glob Import Caveats β Note that: * This is a Vite-only feature and is not a web or ES standard. * The glob patterns are treated like import specifiers: they must be either relative (start with `./`) or absolute (start with `/`, resolved relative to project root) or an alias path (see `resolve.alias` option). * The glob matching is done via `tinyglobby`. * You should also be aware that all the arguments in the `import.meta.glob` must be **passed as literals**. You can NOT use variables or expressions in them. ## Dynamic Import β Similar to glob import, Vite also supports dynamic import with variables. ts const module = await import(`./dir/${file}.js`) Note that variables only represent file names one level deep. If `file` is `'foo/bar'`, the import would fail. For more advanced usage, you can use the glob import feature. ## WebAssembly β Pre-compiled `.wasm` files can be imported with `?init`. The default export will be an initialization function that returns a Promise of the `WebAssembly.Instance`: js import init from './example.wasm?init' init().then((instance) => { instance.exports.test() }) The init function can also take an importObject which is passed along to `WebAssembly.instantiate` as its second argument: js init({ imports: { someFunc: () => { /* ... */ }, }, }).then(() => { /* ... */ }) In the production build, `.wasm` files smaller than `assetInlineLimit` will be inlined as base64 strings. Otherwise, they will be treated as a static asset and fetched on-demand. NOTE ES Module Integration Proposal for WebAssembly is not currently supported. Use `vite-plugin-wasm` or other community plugins to handle this. ### Accessing the WebAssembly Module β If you need access to the `Module` object, e.g. to instantiate it multiple times, use an explicit URL import to resolve the asset, and then perform the instantiation: js import wasmUrl from 'foo.wasm?url' const main = async () => { const responsePromise = fetch(wasmUrl) const { module, instance } = await WebAssembly.instantiateStreaming(responsePromise) /* ... */ } main() ### Fetching the module in Node.js β In SSR, the `fetch()` happening as part of the `?init` import, may fail with `TypeError: Invalid URL`. See the issue Support wasm in SSR. Here is an alternative, assuming the project base is the current directory: js import wasmUrl from 'foo.wasm?url' import { readFile } from 'node:fs/promises' const main = async () => { const resolvedUrl = (await import('./test/boot.test.wasm?url')).default const buffer = await readFile('.' + resolvedUrl) const { instance } = await WebAssembly.instantiate(buffer, { /* ... */ }) /* ... */ } main() ## Web Workers β ### Import with Constructors β A web worker script can be imported using `new Worker()` and `new SharedWorker()`. Compared to the worker suffixes, this syntax leans closer to the standards and is the **recommended** way to create workers. ts const worker = new Worker(new URL('./worker.js', import.meta.url)) The worker constructor also accepts options, which can be used to create "module" workers: ts const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module', }) The worker detection will only work if the `new URL()` constructor is used directly inside the `new Worker()` declaration. Additionally, all options parameters must be static values (i.e. string literals). ### Import with Query Suffixes β A web worker script can be directly imported by appending `?worker` or `?sharedworker` to the import request. The default export will be a custom worker constructor: js import MyWorker from './worker?worker' const worker = new MyWorker() The worker script can also use ESM `import` statements instead of `importScripts()`. **Note**: During development this relies on browser native support, but for the production build it is compiled away. By default, the worker script will be emitted as a separate chunk in the production build. If you wish to inline the worker as base64 strings, add the `inline` query: js import MyWorker from './worker?worker&inline' If you wish to retrieve the worker as a URL, add the `url` query: js import MyWorker from './worker?worker&url' See Worker Options for details on configuring the bundling of all workers. ## Content Security Policy (CSP) β To deploy CSP, certain directives or configs must be set due to Vite's internals. ### `'nonce-{RANDOM}'` β When `html.cspNonce` is set, Vite adds a nonce attribute with the specified value to any `<script>` and `<style>` tags, as well as `<link>` tags for stylesheets and module preloading. Additionally, when this option is set, Vite will inject a meta tag (`<meta property="csp-nonce" nonce="PLACEHOLDER" />`). The nonce value of a meta tag with `property="csp-nonce"` will be used by Vite whenever necessary during both dev and after build. WARNING Ensure that you replace the placeholder with a unique value for each request. This is important to prevent bypassing a resource's policy, which can otherwise be easily done. ### `data:` β By default, during build, Vite inlines small assets as data URIs. Allowing `data:` for related directives (e.g. `img-src`, `font-src`), or, disabling it by setting `build.assetsInlineLimit: 0` is necessary. WARNING Do not allow `data:` for `script-src`. It will allow injection of arbitrary scripts. ## Build Optimizations β > Features listed below are automatically applied as part of the build process and there is no need for explicit configuration unless you want to disable them. ### CSS Code Splitting β Vite automatically extracts the CSS used by modules in an async chunk and generates a separate file for it. The CSS file is automatically loaded via a `<link>` tag when the associated async chunk is loaded, and the async chunk is guaranteed to only be evaluated after the CSS is loaded to avoid FOUC. If you'd rather have all the CSS extracted into a single file, you can disable CSS code splitting by setting `build.cssCodeSplit` to `false`. ### Preload Directives Generation β Vite automatically generates `<link rel="modulepreload">` directives for entry chunks and their direct imports in the built HTML. ### Async Chunk Loading Optimization β In real world applications, Rollup often generates "common" chunks - code that is shared between two or more other chunks. Combined with dynamic imports, it is quite common to have the following scenario: Entry async chunk A common chunk C async chunk B dynamic import direct import In the non-optimized scenarios, when async chunk `A` is imported, the browser will have to request and parse `A` before it can figure out that it also needs the common chunk `C`. This results in an extra network roundtrip: Entry ---> A ---> C Vite automatically rewrites code-split dynamic import calls with a preload step so that when `A` is requested, `C` is fetched **in parallel**: Entry ---> (A + C) It is possible for `C` to have further imports, which will result in even more roundtrips in the un-optimized scenario. Vite's optimization will trace all the direct imports to completely eliminate the roundtrips regardless of import depth. --- ## Page: https://vite.dev/guide/cli # Command Line Interface β ## Dev server β ### `vite` β Start Vite dev server in the current directory. `vite dev` and `vite serve` are aliases for `vite`. #### Usage β bash vite [root] #### Options β | Options | | | --- | --- | | `--host [host]` | Specify hostname (`string`) | | `--port <port>` | Specify port (`number`) | | `--open [path]` | Open browser on startup (`boolean | string`) | | `--cors` | Enable CORS (`boolean`) | | `--strictPort` | Exit if specified port is already in use (`boolean`) | | `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) | | `-c, --config <file>` | Use specified config file (`string`) | | `--base <path>` | Public base path (default: `/`) (`string`) | | `-l, --logLevel <level>` | info | warn | error | silent (`string`) | | `--clearScreen` | Allow/disable clear screen when logging (`boolean`) | | `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild, or `runner` (experimental) to process it on the fly, or `native` (experimental) to load using the native runtime (default: `bundle`) | | `--profile` | Start built-in Node.js inspector (check Performance bottlenecks) | | `-d, --debug [feat]` | Show debug logs (`string | boolean`) | | `-f, --filter <filter>` | Filter debug logs (`string`) | | `-m, --mode <mode>` | Set env mode (`string`) | | `-h, --help` | Display available CLI options | | `-v, --version` | Display version number | ## Build β ### `vite build` β Build for production. #### Usage β bash vite build [root] #### Options β | Options | | | --- | --- | | `--target <target>` | Transpile target (default: `"modules"`) (`string`) | | `--outDir <dir>` | Output directory (default: `dist`) (`string`) | | `--assetsDir <dir>` | Directory under outDir to place assets in (default: `"assets"`) (`string`) | | `--assetsInlineLimit <number>` | Static asset base64 inline threshold in bytes (default: `4096`) (`number`) | | `--ssr [entry]` | Build specified entry for server-side rendering (`string`) | | `--sourcemap [output]` | Output source maps for build (default: `false`) (`boolean | "inline" | "hidden"`) | | `--minify [minifier]` | Enable/disable minification, or specify minifier to use (default: `"esbuild"`) (`boolean | "terser" | "esbuild"`) | | `--manifest [name]` | Emit build manifest json (`boolean | string`) | | `--ssrManifest [name]` | Emit ssr manifest json (`boolean | string`) | | `--emptyOutDir` | Force empty outDir when it's outside of root (`boolean`) | | `-w, --watch` | Rebuilds when modules have changed on disk (`boolean`) | | `-c, --config <file>` | Use specified config file (`string`) | | `--base <path>` | Public base path (default: `/`) (`string`) | | `-l, --logLevel <level>` | Info | warn | error | silent (`string`) | | `--clearScreen` | Allow/disable clear screen when logging (`boolean`) | | `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`) | | `--profile` | Start built-in Node.js inspector (check Performance bottlenecks) | | `-d, --debug [feat]` | Show debug logs (`string | boolean`) | | `-f, --filter <filter>` | Filter debug logs (`string`) | | `-m, --mode <mode>` | Set env mode (`string`) | | `-h, --help` | Display available CLI options | | `--app` | Build all environments, same as `builder: {}` (`boolean`, experimental) | ## Others β ### `vite optimize` β Pre-bundle dependencies. **Deprecated**: the pre-bundle process runs automatically and does not need to be called. #### Usage β bash vite optimize [root] #### Options β | Options | | | --- | --- | | `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) | | `-c, --config <file>` | Use specified config file (`string`) | | `--base <path>` | Public base path (default: `/`) (`string`) | | `-l, --logLevel <level>` | Info | warn | error | silent (`string`) | | `--clearScreen` | Allow/disable clear screen when logging (`boolean`) | | `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`) | | `-d, --debug [feat]` | Show debug logs (`string | boolean`) | | `-f, --filter <filter>` | Filter debug logs (`string`) | | `-m, --mode <mode>` | Set env mode (`string`) | | `-h, --help` | Display available CLI options | ### `vite preview` β Locally preview the production build. Do not use this as a production server as it's not designed for it. #### Usage β bash vite preview [root] #### Options β | Options | | | --- | --- | | `--host [host]` | Specify hostname (`string`) | | `--port <port>` | Specify port (`number`) | | `--strictPort` | Exit if specified port is already in use (`boolean`) | | `--open [path]` | Open browser on startup (`boolean | string`) | | `--outDir <dir>` | Output directory (default: `dist`)(`string`) | | `-c, --config <file>` | Use specified config file (`string`) | | `--base <path>` | Public base path (default: `/`) (`string`) | | `-l, --logLevel <level>` | Info | warn | error | silent (`string`) | | `--clearScreen` | Allow/disable clear screen when logging (`boolean`) | | `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`) | | `-d, --debug [feat]` | Show debug logs (`string | boolean`) | | `-f, --filter <filter>` | Filter debug logs (`string`) | | `-m, --mode <mode>` | Set env mode (`string`) | | `-h, --help` | Display available CLI options | --- ## Page: https://vite.dev/guide/using-plugins # Using Plugins β Vite can be extended using plugins, which are based on Rollup's well-designed plugin interface with a few extra Vite-specific options. This means that Vite users can rely on the mature ecosystem of Rollup plugins, while also being able to extend the dev server and SSR functionality as needed. ## Adding a Plugin β To use a plugin, it needs to be added to the `devDependencies` of the project and included in the `plugins` array in the `vite.config.js` config file. For example, to provide support for legacy browsers, the official @vitejs/plugin-legacy can be used: $ npm add -D @vitejs/plugin-legacy vite.config.js js import legacy from '@vitejs/plugin-legacy' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ legacy({ targets: ['defaults', 'not IE 11'], }), ], }) `plugins` also accepts presets including several plugins as a single element. This is useful for complex features (like framework integration) that are implemented using several plugins. The array will be flattened internally. Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. ## Finding Plugins β NOTE Vite aims to provide out-of-the-box support for common web development patterns. Before searching for a Vite or compatible Rollup plugin, check out the Features Guide. A lot of the cases where a plugin would be needed in a Rollup project are already covered in Vite. Check out the Plugins section for information about official plugins. Community plugins are listed in awesome-vite. You can also find plugins that follow the recommended conventions using a npm search for vite-plugin for Vite plugins or a npm search for rollup-plugin for Rollup plugins. ## Enforcing Plugin Ordering β For compatibility with some Rollup plugins, it may be needed to enforce the order of the plugin or only apply at build time. This should be an implementation detail for Vite plugins. You can enforce the position of a plugin with the `enforce` modifier: * `pre`: invoke plugin before Vite core plugins * default: invoke plugin after Vite core plugins * `post`: invoke plugin after Vite build plugins vite.config.js js import image from '@rollup/plugin-image' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ { ...image(), enforce: 'pre', }, ], }) Check out Plugins API Guide for detailed information. ## Conditional Application β By default, plugins are invoked for both serve and build. In cases where a plugin needs to be conditionally applied only during serve or build, use the `apply` property to only invoke them during `'build'` or `'serve'`: vite.config.js js import typescript2 from 'rollup-plugin-typescript2' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ { ...typescript2(), apply: 'build', }, ], }) ## Building Plugins β Check out the Plugins API Guide for documentation about creating plugins. --- ## Page: https://vite.dev/guide/dep-pre-bundling # Dependency Pre-Bundling β When you run `vite` for the first time, Vite prebundles your project dependencies before loading your site locally. It is done automatically and transparently by default. ## The Why β This is Vite performing what we call "dependency pre-bundling". This process serves two purposes: 1. **CommonJS and UMD compatibility:** During development, Vite's dev serves all code as native ESM. Therefore, Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first. When converting CommonJS dependencies, Vite performs smart import analysis so that named imports to CommonJS modules will work as expected even if the exports are dynamically assigned (e.g. React): js // works as expected import React, { useState } from 'react' 2. **Performance:** Vite converts ESM dependencies with many internal modules into a single module to improve subsequent page load performance. Some packages ship their ES modules builds as many separate files importing one another. For example, `lodash-es` has over 600 internal modules! When we do `import { debounce } from 'lodash-es'`, the browser fires off 600+ HTTP requests at the same time! Even though the server has no problem handling them, the large amount of requests create a network congestion on the browser side, causing the page to load noticeably slower. By pre-bundling `lodash-es` into a single module, we now only need one HTTP request instead! NOTE Dependency pre-bundling only applies in development mode, and uses `esbuild` to convert dependencies to ESM. In production builds, `@rollup/plugin-commonjs` is used instead. ## Automatic Dependency Discovery β If an existing cache is not found, Vite will crawl your source code and automatically discover dependency imports (i.e. "bare imports" that expect to be resolved from `node_modules`) and use these found imports as entry points for the pre-bundle. The pre-bundling is performed with `esbuild` so it's typically very fast. After the server has already started, if a new dependency import is encountered that isn't already in the cache, Vite will re-run the dep bundling process and reload the page if needed. ## Monorepos and Linked Dependencies β In a monorepo setup, a dependency may be a linked package from the same repo. Vite automatically detects dependencies that are not resolved from `node_modules` and treats the linked dep as source code. It will not attempt to bundle the linked dep, and will analyze the linked dep's dependency list instead. However, this requires the linked dep to be exported as ESM. If not, you can add the dependency to `optimizeDeps.include` and `build.commonjsOptions.include` in your config. vite.config.js js export default defineConfig({ optimizeDeps: { include: ['linked-dep'], }, build: { commonjsOptions: { include: [/linked-dep/, /node_modules/], }, }, }) When making changes to the linked dep, restart the dev server with the `--force` command line option for the changes to take effect. ## Customizing the Behavior β The default dependency discovery heuristics may not always be desirable. In cases where you want to explicitly include/exclude dependencies from the list, use the `optimizeDeps` config options. A typical use case for `optimizeDeps.include` or `optimizeDeps.exclude` is when you have an import that is not directly discoverable in the source code. For example, maybe the import is created as a result of a plugin transform. This means Vite won't be able to discover the import on the initial scan - it can only discover it after the file is requested by the browser and transformed. This will cause the server to immediately re-bundle after server start. Both `include` and `exclude` can be used to deal with this. If the dependency is large (with many internal modules) or is CommonJS, then you should include it; If the dependency is small and is already valid ESM, you can exclude it and let the browser load it directly. You can further customize esbuild too with the `optimizeDeps.esbuildOptions` option. For example, adding an esbuild plugin to handle special files in dependencies or changing the build `target`. ## Caching β ### File System Cache β Vite caches the pre-bundled dependencies in `node_modules/.vite`. It determines whether it needs to re-run the pre-bundling step based on a few sources: * Package manager lockfile content, e.g. `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` or `bun.lockb`. * Patches folder modification time. * Relevant fields in your `vite.config.js`, if present. * `NODE_ENV` value. The pre-bundling step will only need to be re-run when one of the above has changed. If for some reason you want to force Vite to re-bundle deps, you can either start the dev server with the `--force` command line option, or manually delete the `node_modules/.vite` cache directory. ### Browser Cache β Resolved dependency requests are strongly cached with HTTP headers `max-age=31536000,immutable` to improve page reload performance during dev. Once cached, these requests will never hit the dev server again. They are auto invalidated by the appended version query if a different version is installed (as reflected in your package manager lockfile). If you want to debug your dependencies by making local edits, you can: 1. Temporarily disable cache via the Network tab of your browser devtools; 2. Restart Vite dev server with the `--force` flag to re-bundle the deps; 3. Reload the page. --- ## Page: https://vite.dev/guide/assets # Static Asset Handling β * Related: Public Base Path * Related: `assetsInclude` config option ## Importing Asset as URL β Importing a static asset will return the resolved public URL when it is served: js import imgUrl from './img.png' document.getElementById('hero-img').src = imgUrl For example, `imgUrl` will be `/src/img.png` during development, and become `/assets/img.2d8efhg.png` in the production build. The behavior is similar to webpack's `file-loader`. The difference is that the import can be either using absolute public paths (based on project root during dev) or relative paths. * `url()` references in CSS are handled the same way. * If using the Vue plugin, asset references in Vue SFC templates are automatically converted into imports. * Common image, media, and font filetypes are detected as assets automatically. You can extend the internal list using the `assetsInclude` option. * Referenced assets are included as part of the build assets graph, will get hashed file names, and can be processed by plugins for optimization. * Assets smaller in bytes than the `assetsInlineLimit` option will be inlined as base64 data URLs. * Git LFS placeholders are automatically excluded from inlining because they do not contain the content of the file they represent. To get inlining, make sure to download the file contents via Git LFS before building. * TypeScript, by default, does not recognize static asset imports as valid modules. To fix this, include `vite/client`. Inlining SVGs through `url()` When passing a URL of SVG to a manually constructed `url()` by JS, the variable should be wrapped within double quotes. js import imgUrl from './img.svg' document.getElementById('hero-img').style.background = `url("${imgUrl}")` ### Explicit URL Imports β Assets that are not included in the internal list or in `assetsInclude`, can be explicitly imported as a URL using the `?url` suffix. This is useful, for example, to import Houdini Paint Worklets. js import workletURL from 'extra-scalloped-border/worklet.js?url' CSS.paintWorklet.addModule(workletURL) ### Explicit Inline Handling β Assets can be explicitly imported with inlining or no inlining using the `?inline` or `?no-inline` suffix respectively. js import imgUrl1 from './img.svg?no-inline' import imgUrl2 from './img.png?inline' ### Importing Asset as String β Assets can be imported as strings using the `?raw` suffix. js import shaderString from './shader.glsl?raw' ### Importing Script as a Worker β Scripts can be imported as web workers with the `?worker` or `?sharedworker` suffix. js // Separate chunk in the production build import Worker from './shader.js?worker' const worker = new Worker() js // sharedworker import SharedWorker from './shader.js?sharedworker' const sharedWorker = new SharedWorker() js // Inlined as base64 strings import InlineWorker from './shader.js?worker&inline' Check out the Web Worker section for more details. ## The `public` Directory β If you have assets that are: * Never referenced in source code (e.g. `robots.txt`) * Must retain the exact same file name (without hashing) * ...or you simply don't want to have to import an asset first just to get its URL Then you can place the asset in a special `public` directory under your project root. Assets in this directory will be served at root path `/` during dev, and copied to the root of the dist directory as-is. The directory defaults to `<root>/public`, but can be configured via the `publicDir` option. Note that you should always reference `public` assets using root absolute path - for example, `public/icon.png` should be referenced in source code as `/icon.png`. ## new URL(url, import.meta.url) β import.meta.url is a native ESM feature that exposes the current module's URL. Combining it with the native URL constructor, we can obtain the full, resolved URL of a static asset using relative path from a JavaScript module: js const imgUrl = new URL('./img.png', import.meta.url).href document.getElementById('hero-img').src = imgUrl This works natively in modern browsers - in fact, Vite doesn't need to process this code at all during development! This pattern also supports dynamic URLs via template literals: js function getImageUrl(name) { // note that this does not include files in subdirectories return new URL(`./dir/${name}.png`, import.meta.url).href } During the production build, Vite will perform necessary transforms so that the URLs still point to the correct location even after bundling and asset hashing. However, the URL string must be static so it can be analyzed, otherwise the code will be left as is, which can cause runtime errors if `build.target` does not support `import.meta.url` js // Vite will not transform this const imgUrl = new URL(imagePath, import.meta.url).href How it works Vite will transform the `getImageUrl` function to: js import __img0png from './dir/img0.png' import __img1png from './dir/img1.png' function getImageUrl(name) { const modules = { './dir/img0.png': __img0png, './dir/img1.png': __img1png, } return new URL(modules[`./dir/${name}.png`], import.meta.url).href } Does not work with SSR This pattern does not work if you are using Vite for Server-Side Rendering, because `import.meta.url` have different semantics in browsers vs. Node.js. The server bundle also cannot determine the client host URL ahead of time. --- ## Page: https://vite.dev/guide/build # Building for Production β When it is time to deploy your app for production, simply run the `vite build` command. By default, it uses `<root>/index.html` as the build entry point, and produces an application bundle that is suitable to be served over a static hosting service. Check out the Deploying a Static Site for guides about popular services. ## Browser Compatibility β By default, the production bundle assumes support for modern JavaScript, such as native ES Modules, native ESM dynamic import, `import.meta`, nullish coalescing, and BigInt. The default browser support range is: * Chrome >=87 * Firefox >=78 * Safari >=14 * Edge >=88 You can specify custom targets via the `build.target` config option, where the lowest target is `es2015`. If a lower target is set, Vite will still require these minimum browser support ranges as it relies on native ESM dynamic import, and `import.meta`: * Chrome >=64 * Firefox >=67 * Safari >=11.1 * Edge >=79 Note that by default, Vite only handles syntax transforms and **does not cover polyfills**. You can check out https://cdnjs.cloudflare.com/polyfill/ which automatically generates polyfill bundles based on the user's browser UserAgent string. Legacy browsers can be supported via @vitejs/plugin-legacy, which will automatically generate legacy chunks and corresponding ES language feature polyfills. The legacy chunks are conditionally loaded only in browsers that do not have native ESM support. ## Public Base Path β * Related: Asset Handling If you are deploying your project under a nested public path, simply specify the `base` config option and all asset paths will be rewritten accordingly. This option can also be specified as a command line flag, e.g. `vite build --base=/my/public/path/`. JS-imported asset URLs, CSS `url()` references, and asset references in your `.html` files are all automatically adjusted to respect this option during build. The exception is when you need to dynamically concatenate URLs on the fly. In this case, you can use the globally injected `import.meta.env.BASE_URL` variable which will be the public base path. Note this variable is statically replaced during build so it must appear exactly as-is (i.e. `import.meta.env['BASE_URL']` won't work). For advanced base path control, check out Advanced Base Options. ### Relative base β If you don't know the base path in advance, you may set a relative base path with `"base": "./"` or `"base": ""`. This will make all generated URLs to be relative to each file. Support for older browsers when using relative bases `import.meta` support is required for relative bases. If you need to support browsers that do not support `import.meta`, you can use the `legacy` plugin. ## Customizing the Build β The build can be customized via various build config options. Specifically, you can directly adjust the underlying Rollup options via `build.rollupOptions`: vite.config.js js export default defineConfig({ build: { rollupOptions: { // https://rollupjs.org/configuration-options/ }, }, }) For example, you can specify multiple Rollup outputs with plugins that are only applied during build. ## Chunking Strategy β You can configure how chunks are split using `build.rollupOptions.output.manualChunks` (see Rollup docs). If you use a framework, refer to their documentation for configuring how chunks are splitted. ## Load Error Handling β Vite emits `vite:preloadError` event when it fails to load dynamic imports. `event.payload` contains the original import error. If you call `event.preventDefault()`, the error will not be thrown. js window.addEventListener('vite:preloadError', (event) => { window.location.reload() // for example, refresh the page }) When a new deployment occurs, the hosting service may delete the assets from previous deployments. As a result, a user who visited your site before the new deployment might encounter an import error. This error happens because the assets running on that user's device are outdated and it tries to import the corresponding old chunk, which is deleted. This event is useful for addressing this situation. ## Rebuild on Files Changes β You can enable rollup watcher with `vite build --watch`. Or, you can directly adjust the underlying `WatcherOptions` via `build.watch`: vite.config.js js export default defineConfig({ build: { watch: { // https://rollupjs.org/configuration-options/#watch }, }, }) With the `--watch` flag enabled, changes to the `vite.config.js`, as well as any files to be bundled, will trigger a rebuild. ## Multi-Page App β Suppose you have the following source code structure: βββ package.json βββ vite.config.js βββ index.html βββ main.js βββ nested βββ index.html βββ nested.js During dev, simply navigate or link to `/nested/` - it works as expected, just like for a normal static file server. During build, all you need to do is to specify multiple `.html` files as entry points: vite.config.js js import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { defineConfig } from 'vite' const __dirname = dirname(fileURLToPath(import.meta.url)) export default defineConfig({ build: { rollupOptions: { input: { main: resolve(__dirname, 'index.html'), nested: resolve(__dirname, 'nested/index.html'), }, }, }, }) If you specify a different root, remember that `__dirname` will still be the folder of your vite.config.js file when resolving the input paths. Therefore, you will need to add your `root` entry to the arguments for `resolve`. Note that for HTML files, Vite ignores the name given to the entry in the `rollupOptions.input` object and instead respects the resolved id of the file when generating the HTML asset in the dist folder. This ensures a consistent structure with the way the dev server works. ## Library Mode β When you are developing a browser-oriented library, you are likely spending most of the time on a test/demo page that imports your actual library. With Vite, you can use your `index.html` for that purpose to get the smooth development experience. When it is time to bundle your library for distribution, use the `build.lib` config option. Make sure to also externalize any dependencies that you do not want to bundle into your library, e.g. `vue` or `react`: vite.config.js (single entry)vite.config.js (multiple entries) js import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { defineConfig } from 'vite' const __dirname = dirname(fileURLToPath(import.meta.url)) export default defineConfig({ build: { lib: { entry: resolve(__dirname, 'lib/main.js'), name: 'MyLib', // the proper extensions will be added fileName: 'my-lib', }, rollupOptions: { // make sure to externalize deps that shouldn't be bundled // into your library external: ['vue'], output: { // Provide global variables to use in the UMD build // for externalized deps globals: { vue: 'Vue', }, }, }, }, }) js import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { defineConfig } from 'vite' const __dirname = dirname(fileURLToPath(import.meta.url)) export default defineConfig({ build: { lib: { entry: { 'my-lib': resolve(__dirname, 'lib/main.js'), secondary: resolve(__dirname, 'lib/secondary.js'), }, name: 'MyLib', }, rollupOptions: { // make sure to externalize deps that shouldn't be bundled // into your library external: ['vue'], output: { // Provide global variables to use in the UMD build // for externalized deps globals: { vue: 'Vue', }, }, }, }, }) The entry file would contain exports that can be imported by users of your package: lib/main.js js import Foo from './Foo.vue' import Bar from './Bar.vue' export { Foo, Bar } Running `vite build` with this config uses a Rollup preset that is oriented towards shipping libraries and produces two bundle formats: * `es` and `umd` (for single entry) * `es` and `cjs` (for multiple entries) The formats can be configured with the `build.lib.formats` option. $ vite build building for production... dist/my-lib.js 0.08 kB / gzip: 0.07 kB dist/my-lib.umd.cjs 0.30 kB / gzip: 0.16 kB Recommended `package.json` for your lib: package.json (single entry)package.json (multiple entries) json { "name": "my-lib", "type": "module", "files": ["dist"], "main": "./dist/my-lib.umd.cjs", "module": "./dist/my-lib.js", "exports": { ".": { "import": "./dist/my-lib.js", "require": "./dist/my-lib.umd.cjs" } } } json { "name": "my-lib", "type": "module", "files": ["dist"], "main": "./dist/my-lib.cjs", "module": "./dist/my-lib.js", "exports": { ".": { "import": "./dist/my-lib.js", "require": "./dist/my-lib.cjs" }, "./secondary": { "import": "./dist/secondary.js", "require": "./dist/secondary.cjs" } } } ### CSS support β If your library imports any CSS, it will be bundled as a single CSS file besides the built JS files, e.g. `dist/my-lib.css`. The name defaults to `build.lib.fileName`, but can also be changed with `build.lib.cssFileName`. You can export the CSS file in your `package.json` to be imported by users: json { "name": "my-lib", "type": "module", "files": ["dist"], "main": "./dist/my-lib.umd.cjs", "module": "./dist/my-lib.js", "exports": { ".": { "import": "./dist/my-lib.js", "require": "./dist/my-lib.umd.cjs" }, "./style.css": "./dist/my-lib.css" } } File Extensions If the `package.json` does not contain `"type": "module"`, Vite will generate different file extensions for Node.js compatibility. `.js` will become `.mjs` and `.cjs` will become `.js`. Environment Variables In library mode, all `import.meta.env.*` usage are statically replaced when building for production. However, `process.env.*` usage are not, so that consumers of your library can dynamically change it. If this is undesirable, you can use `define: { 'process.env.NODE_ENV': '"production"' }` for example to statically replace them, or use `esm-env` for better compatibility with bundlers and runtimes. Advanced Usage Library mode includes a simple and opinionated configuration for browser-oriented and JS framework libraries. If you are building non-browser libraries, or require advanced build flows, you can use Rollup or esbuild directly. ## Advanced Base Options β WARNING This feature is experimental. Give Feedback. For advanced use cases, the deployed assets and public files may be in different paths, for example to use different cache strategies. A user may choose to deploy in three different paths: * The generated entry HTML files (which may be processed during SSR) * The generated hashed assets (JS, CSS, and other file types like images) * The copied public files A single static base isn't enough in these scenarios. Vite provides experimental support for advanced base options during build, using `experimental.renderBuiltUrl`. ts experimental: { renderBuiltUrl(filename, { hostType }) { if (hostType === 'js') { return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` } } else { return { relative: true } } }, }, If the hashed assets and public files aren't deployed together, options for each group can be defined independently using asset `type` included in the second `context` param given to the function. ts experimental: { renderBuiltUrl(filename, { hostId, hostType, type }) { if (type === 'public') { return 'https://www.domain.com/' + filename } else if (path.extname(hostId) === '.js') { return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` } } else { return 'https://cdn.domain.com/assets/' + filename } }, }, Note that the `filename` passed is a decoded URL, and if the function returns a URL string, it should also be decoded. Vite will handle the encoding automatically when rendering the URLs. If an object with `runtime` is returned, encoding should be handled yourself where needed as the runtime code will be rendered as is. --- ## Page: https://vite.dev/guide/static-deploy # Deploying a Static Site β The following guides are based on some shared assumptions: * You are using the default build output location (`dist`). This location can be changed using `build.outDir`, and you can extrapolate instructions from these guides in that case. * You are using npm. You can use equivalent commands to run the scripts if you are using Yarn or other package managers. * Vite is installed as a local dev dependency in your project, and you have setup the following npm scripts: package.json json { "scripts": { "build": "vite build", "preview": "vite preview" } } It is important to note that `vite preview` is intended for previewing the build locally and not meant as a production server. NOTE These guides provide instructions for performing a static deployment of your Vite site. Vite also supports Server Side Rendering. SSR refers to front-end frameworks that support running the same application in Node.js, pre-rendering it to HTML, and finally hydrating it on the client. Check out the SSR Guide to learn about this feature. On the other hand, if you are looking for integration with traditional server-side frameworks, check out the Backend Integration guide instead. ## Building the App β You may run `npm run build` command to build the app. bash $ npm run build By default, the build output will be placed at `dist`. You may deploy this `dist` folder to any of your preferred platforms. ### Testing the App Locally β Once you've built the app, you may test it locally by running `npm run preview` command. bash $ npm run preview The `vite preview` command will boot up a local static web server that serves the files from `dist` at `http://localhost:4173`. It's an easy way to check if the production build looks OK in your local environment. You may configure the port of the server by passing the `--port` flag as an argument. package.json json { "scripts": { "preview": "vite preview --port 8080" } } Now the `preview` command will launch the server at `http://localhost:8080`. ## GitHub Pages β 1. Set the correct `base` in `vite.config.js`. If you are deploying to `https://<USERNAME>.github.io/`, or to a custom domain through GitHub Pages (eg. `www.example.com`), set `base` to `'/'`. Alternatively, you can remove `base` from the configuration, as it defaults to `'/'`. If you are deploying to `https://<USERNAME>.github.io/<REPO>/` (eg. your repository is at `https://github.com/<USERNAME>/<REPO>`), then set `base` to `'/<REPO>/'`. 2. Go to your GitHub Pages configuration in the repository settings page and choose the source of deployment as "GitHub Actions", this will lead you to create a workflow that builds and deploys your project, a sample workflow that installs dependencies and builds using npm is provided: yml # Simple workflow for deploying static content to GitHub Pages name: Deploy static content to Pages on: # Runs on pushes targeting the default branch push: branches: ['main'] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: 'pages' cancel-in-progress: true jobs: # Single deploy job since we're just deploying deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Node uses: actions/setup-node@v4 with: node-version: 20 cache: 'npm' - name: Install dependencies run: npm ci - name: Build run: npm run build - name: Setup Pages uses: actions/configure-pages@v4 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: # Upload dist folder path: './dist' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ## GitLab Pages and GitLab CI β 1. Set the correct `base` in `vite.config.js`. If you are deploying to `https://<USERNAME or GROUP>.gitlab.io/`, you can omit `base` as it defaults to `'/'`. If you are deploying to `https://<USERNAME or GROUP>.gitlab.io/<REPO>/`, for example your repository is at `https://gitlab.com/<USERNAME>/<REPO>`, then set `base` to `'/<REPO>/'`. 2. Create a file called `.gitlab-ci.yml` in the root of your project with the content below. This will build and deploy your site whenever you make changes to your content: .gitlab-ci.yml yaml image: node:16.5.0 pages: stage: deploy cache: key: files: - package-lock.json prefix: npm paths: - node_modules/ script: - npm install - npm run build - cp -a dist/. public/ artifacts: paths: - public rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH ## Netlify β ### Netlify CLI β 1. Install the Netlify CLI. 2. Create a new site using `ntl init`. 3. Deploy using `ntl deploy`. bash # Install the Netlify CLI $ npm install -g netlify-cli # Create a new site in Netlify $ ntl init # Deploy to a unique preview URL $ ntl deploy The Netlify CLI will share with you a preview URL to inspect. When you are ready to go into production, use the `prod` flag: bash # Deploy the site into production $ ntl deploy --prod ### Netlify with Git β 1. Push your code to a git repository (GitHub, GitLab, BitBucket, Azure DevOps). 2. Import the project to Netlify. 3. Choose the branch, output directory, and set up environment variables if applicable. 4. Click on **Deploy**. 5. Your Vite app is deployed! After your project has been imported and deployed, all subsequent pushes to branches other than the production branch along with pull requests will generate Preview Deployments, and all changes made to the Production Branch (commonly βmainβ) will result in a Production Deployment. ## Vercel β ### Vercel CLI β 1. Install the Vercel CLI and run `vercel` to deploy. 2. Vercel will detect that you are using Vite and will enable the correct settings for your deployment. 3. Your application is deployed! (e.g. vite-vue-template.vercel.app) bash $ npm i -g vercel $ vercel init vite Vercel CLI > Success! Initialized "vite" example in ~/your-folder. - To deploy, `cd vite` and run `vercel`. ### Vercel for Git β 1. Push your code to your git repository (GitHub, GitLab, Bitbucket). 2. Import your Vite project into Vercel. 3. Vercel will detect that you are using Vite and will enable the correct settings for your deployment. 4. Your application is deployed! (e.g. vite-vue-template.vercel.app) After your project has been imported and deployed, all subsequent pushes to branches will generate Preview Deployments, and all changes made to the Production Branch (commonly βmainβ) will result in a Production Deployment. Learn more about Vercelβs Git Integration. ## Cloudflare Pages β ### Cloudflare Pages via Wrangler β 1. Install Wrangler CLI. 2. Authenticate Wrangler with your Cloudflare account using `wrangler login`. 3. Run your build command. 4. Deploy using `npx wrangler pages deploy dist`. bash # Install Wrangler CLI $ npm install -g wrangler # Login to Cloudflare account from CLI $ wrangler login # Run your build command $ npm run build # Create new deployment $ npx wrangler pages deploy dist After your assets are uploaded, Wrangler will give you a preview URL to inspect your site. When you log into the Cloudflare Pages dashboard, you will see your new project. ### Cloudflare Pages with Git β 1. Push your code to your git repository (GitHub, GitLab). 2. Log in to the Cloudflare dashboard and select your account in **Account Home** > **Pages**. 3. Select **Create a new Project** and the **Connect Git** option. 4. Select the git project you want to deploy and click **Begin setup** 5. Select the corresponding framework preset in the build setting depending on the Vite framework you have selected. 6. Then save and deploy! 7. Your application is deployed! (e.g `https://<PROJECTNAME>.pages.dev/`) After your project has been imported and deployed, all subsequent pushes to branches will generate Preview Deployments unless specified not to in your branch build controls. All changes to the Production Branch (commonly βmainβ) will result in a Production Deployment. You can also add custom domains and handle custom build settings on Pages. Learn more about Cloudflare Pages Git Integration. ## Google Firebase β 1. Make sure you have firebase-tools installed. 2. Create `firebase.json` and `.firebaserc` at the root of your project with the following content: firebase.json json { "hosting": { "public": "dist", "ignore": [], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } .firebaserc js { "projects": { "default": "<YOUR_FIREBASE_ID>" } } 3. After running `npm run build`, deploy using the command `firebase deploy`. ## Surge β 1. First install surge, if you havenβt already. 2. Run `npm run build`. 3. Deploy to surge by typing `surge dist`. You can also deploy to a custom domain by adding `surge dist yourdomain.com`. ## Azure Static Web Apps β You can quickly deploy your Vite app with Microsoft Azure Static Web Apps service. You need: * An Azure account and a subscription key. You can create a free Azure account here. * Your app code pushed to GitHub. * The SWA Extension in Visual Studio Code. Install the extension in VS Code and navigate to your app root. Open the Static Web Apps extension, sign in to Azure, and click the '+' sign to create a new Static Web App. You will be prompted to designate which subscription key to use. Follow the wizard started by the extension to give your app a name, choose a framework preset, and designate the app root (usually `/`) and built file location `/dist`. The wizard will run and will create a GitHub action in your repo in a `.github` folder. The action will work to deploy your app (watch its progress in your repo's Actions tab) and, when successfully completed, you can view your app in the address provided in the extension's progress window by clicking the 'Browse Website' button that appears when the GitHub action has run. ## Render β You can deploy your Vite app as a Static Site on Render. 1. Create a Render account. 2. In the Dashboard, click the **New** button and select **Static Site**. 3. Connect your GitHub/GitLab account or use a public repository. 4. Specify a project name and branch. * **Build Command**: `npm install && npm run build` * **Publish Directory**: `dist` 5. Click **Create Static Site**. Your app should be deployed at `https://<PROJECTNAME>.onrender.com/`. By default, any new commit pushed to the specified branch will automatically trigger a new deployment. Auto-Deploy can be configured in the project settings. You can also add a custom domain to your project. ## Flightcontrol β Deploy your static site using Flightcontrol by following these instructions. ## Kinsta Static Site Hosting β Deploy your static site using Kinsta by following these instructions. ## xmit Static Site Hosting β Deploy your static site using xmit by following this guide. --- ## Page: https://vite.dev/guide/env-and-mode # Env Variables and Modes β Vite exposes certain constants under the special `import.meta.env` object. These constants are defined as global variables during dev and statically replaced at build time to make tree-shaking effective. ## Built-in constants β Some built-in constants are available in all cases: * **`import.meta.env.MODE`**: {string} the mode the app is running in. * **`import.meta.env.BASE_URL`**: {string} the base url the app is being served from. This is determined by the `base` config option. * **`import.meta.env.PROD`**: {boolean} whether the app is running in production (running the dev server with `NODE_ENV='production'` or running an app built with `NODE_ENV='production'`). * **`import.meta.env.DEV`**: {boolean} whether the app is running in development (always the opposite of `import.meta.env.PROD`) * **`import.meta.env.SSR`**: {boolean} whether the app is running in the server. ## Env Variables β Vite exposes env variables under `import.meta.env` object as strings automatically. To prevent accidentally leaking env variables to the client, only variables prefixed with `VITE_` are exposed to your Vite-processed code. e.g. for the following env variables: .env VITE_SOME_KEY=123 DB_PASSWORD=foobar Only `VITE_SOME_KEY` will be exposed as `import.meta.env.VITE_SOME_KEY` to your client source code, but `DB_PASSWORD` will not. js console.log(import.meta.env.VITE_SOME_KEY) // "123" console.log(import.meta.env.DB_PASSWORD) // undefined If you want to customize the env variables prefix, see the envPrefix option. Env parsing As shown above, `VITE_SOME_KEY` is a number but returns a string when parsed. The same would also happen for boolean env variables. Make sure to convert to the desired type when using it in your code. ### `.env` Files β Vite uses dotenv to load additional environment variables from the following files in your environment directory: .env # loaded in all cases .env.local # loaded in all cases, ignored by git .env.[mode] # only loaded in specified mode .env.[mode].local # only loaded in specified mode, ignored by git Env Loading Priorities An env file for a specific mode (e.g. `.env.production`) will take higher priority than a generic one (e.g. `.env`). Vite will always load `.env` and `.env.local` in addition to the mode-specific `.env.[mode]` file. Variables declared in mode-specific files will take precedence over those in generic files, but variables defined only in `.env` or `.env.local` will still be available in the environment. In addition, environment variables that already exist when Vite is executed have the highest priority and will not be overwritten by `.env` files. For example, when running `VITE_SOME_KEY=123 vite build`. `.env` files are loaded at the start of Vite. Restart the server after making changes. Also, Vite uses dotenv-expand to expand variables written in env files out of the box. To learn more about the syntax, check out their docs. Note that if you want to use `$` inside your environment value, you have to escape it with `\`. .env KEY=123 NEW_KEY1=test$foo # test NEW_KEY2=test\$foo # test$foo NEW_KEY3=test$KEY # test123 SECURITY NOTES * `.env.*.local` files are local-only and can contain sensitive variables. You should add `*.local` to your `.gitignore` to avoid them being checked into git. * Since any variables exposed to your Vite source code will end up in your client bundle, `VITE_*` variables should _not_ contain any sensitive information. Expanding variables in reverse order Vite supports expanding variables in reverse order. For example, the `.env` below will be evaluated as `VITE_FOO=foobar`, `VITE_BAR=bar`. .env VITE_FOO=foo${VITE_BAR} VITE_BAR=bar This does not work in shell scripts and other tools like `docker-compose`. That said, Vite supports this behavior as this has been supported by `dotenv-expand` for a long time and other tools in JavaScript ecosystem uses older versions that supports this behavior. To avoid interop issues, it is recommended to avoid relying on this behavior. Vite may start emitting warnings for this behavior in the future. ## IntelliSense for TypeScript β By default, Vite provides type definitions for `import.meta.env` in `vite/client.d.ts`. While you can define more custom env variables in `.env.[mode]` files, you may want to get TypeScript IntelliSense for user-defined env variables that are prefixed with `VITE_`. To achieve this, you can create an `vite-env.d.ts` in `src` directory, then augment `ImportMetaEnv` like this: vite-env.d.ts typescript /// <reference types="vite/client" /> interface ImportMetaEnv { readonly VITE_APP_TITLE: string // more env variables... } interface ImportMeta { readonly env: ImportMetaEnv } If your code relies on types from browser environments such as DOM and WebWorker, you can update the lib field in `tsconfig.json`. tsconfig.json json { "lib": ["WebWorker"] } Imports will break type augmentation If the `ImportMetaEnv` augmentation does not work, make sure you do not have any `import` statements in `vite-env.d.ts`. See the TypeScript documentation for more information. ## HTML Constant Replacement β Vite also supports replacing constants in HTML files. Any properties in `import.meta.env` can be used in HTML files with a special `%CONST_NAME%` syntax: html <h1>Vite is running in %MODE%</h1> <p>Using data from %VITE_API_URL%</p> If the env doesn't exist in `import.meta.env`, e.g. `%NON_EXISTENT%`, it will be ignored and not replaced, unlike `import.meta.env.NON_EXISTENT` in JS where it's replaced as `undefined`. Given that Vite is used by many frameworks, it is intentionally unopinionated about complex replacements like conditionals. Vite can be extended using an existing userland plugin or a custom plugin that implements the `transformIndexHtml` hook. ## Modes β By default, the dev server (`dev` command) runs in `development` mode and the `build` command runs in `production` mode. This means when running `vite build`, it will load the env variables from `.env.production` if there is one: .env.production VITE_APP_TITLE=My App In your app, you can render the title using `import.meta.env.VITE_APP_TITLE`. In some cases, you may want to run `vite build` with a different mode to render a different title. You can overwrite the default mode used for a command by passing the `--mode` option flag. For example, if you want to build your app for a staging mode: bash vite build --mode staging And create a `.env.staging` file: .env.staging VITE_APP_TITLE=My App (staging) As `vite build` runs a production build by default, you can also change this and run a development build by using a different mode and `.env` file configuration: .env.testing NODE_ENV=development ### NODE\_ENV and Modes β It's important to note that `NODE_ENV` (`process.env.NODE_ENV`) and modes are two different concepts. Here's how different commands affect the `NODE_ENV` and mode: | Command | NODE\_ENV | Mode | | --- | --- | --- | | `vite build` | `"production"` | `"production"` | | `vite build --mode development` | `"production"` | `"development"` | | `NODE_ENV=development vite build` | `"development"` | `"production"` | | `NODE_ENV=development vite build --mode development` | `"development"` | `"development"` | The different values of `NODE_ENV` and mode also reflect on its corresponding `import.meta.env` properties: | Command | `import.meta.env.PROD` | `import.meta.env.DEV` | | --- | --- | --- | | `NODE_ENV=production` | `true` | `false` | | `NODE_ENV=development` | `false` | `true` | | `NODE_ENV=other` | `false` | `true` | | Command | `import.meta.env.MODE` | | --- | --- | | `--mode production` | `"production"` | | `--mode development` | `"development"` | | `--mode staging` | `"staging"` | `NODE_ENV` in `.env` files `NODE_ENV=...` can be set in the command, and also in your `.env` file. If `NODE_ENV` is specified in a `.env.[mode]` file, the mode can be used to control its value. However, both `NODE_ENV` and modes remain as two different concepts. The main benefit with `NODE_ENV=...` in the command is that it allows Vite to detect the value early. It also allows you to read `process.env.NODE_ENV` in your Vite config as Vite can only load the env files once the config is evaluated. --- ## Page: https://vite.dev/guide/ssr # Server-Side Rendering (SSR) β Note SSR specifically refers to front-end frameworks (for example React, Preact, Vue, and Svelte) that support running the same application in Node.js, pre-rendering it to HTML, and finally hydrating it on the client. If you are looking for integration with traditional server-side frameworks, check out the Backend Integration guide instead. The following guide also assumes prior experience working with SSR in your framework of choice, and will only focus on Vite-specific integration details. Low-level API This is a low-level API meant for library and framework authors. If your goal is to create an application, make sure to check out the higher-level SSR plugins and tools at Awesome Vite SSR section first. That said, many applications are successfully built directly on top of Vite's native low-level API. Currently, Vite is working on an improved SSR API with the Environment API. Check out the link for more details. ## Example Projects β Vite provides built-in support for server-side rendering (SSR). `create-vite-extra` contains example SSR setups you can use as references for this guide: * Vanilla * Vue * React * Preact * Svelte * Solid You can also scaffold these projects locally by running `create-vite` and choose `Others > create-vite-extra` under the framework option. ## Source Structure β A typical SSR application will have the following source file structure: - index.html - server.js # main application server - src/ - main.js # exports env-agnostic (universal) app code - entry-client.js # mounts the app to a DOM element - entry-server.js # renders the app using the framework's SSR API The `index.html` will need to reference `entry-client.js` and include a placeholder where the server-rendered markup should be injected: index.html html <div id="app"><!--ssr-outlet--></div> <script type="module" src="/src/entry-client.js"></script> You can use any placeholder you prefer instead of `<!--ssr-outlet-->`, as long as it can be precisely replaced. ## Conditional Logic β If you need to perform conditional logic based on SSR vs. client, you can use js if (import.meta.env.SSR) { // ... server only logic } This is statically replaced during build so it will allow tree-shaking of unused branches. ## Setting Up the Dev Server β When building an SSR app, you likely want to have full control over your main server and decouple Vite from the production environment. It is therefore recommended to use Vite in middleware mode. Here is an example with express (v4): server.js js import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import express from 'express' import { createServer as createViteServer } from 'vite' const __dirname = path.dirname(fileURLToPath(import.meta.url)) async function createServer() { const app = express() // Create Vite server in middleware mode and configure the app type as // 'custom', disabling Vite's own HTML serving logic so parent server // can take control const vite = await createViteServer({ server: { middlewareMode: true }, appType: 'custom' }) // Use vite's connect instance as middleware. If you use your own // express router (express.Router()), you should use router.use // When the server restarts (for example after the user modifies // vite.config.js), `vite.middlewares` is still going to be the same // reference (with a new internal stack of Vite and plugin-injected // middlewares). The following is valid even after restarts. app.use(vite.middlewares) app.use('*', async (req, res) => { // serve index.html - we will tackle this next }) app.listen(5173) } createServer() Here `vite` is an instance of ViteDevServer. `vite.middlewares` is a Connect instance which can be used as a middleware in any connect-compatible Node.js framework. The next step is implementing the `*` handler to serve server-rendered HTML: server.js js app.use('*', async (req, res, next) => { const url = req.originalUrl try { // 1. Read index.html let template = fs.readFileSync( path.resolve(__dirname, 'index.html'), 'utf-8', ) // 2. Apply Vite HTML transforms. This injects the Vite HMR client, // and also applies HTML transforms from Vite plugins, e.g. global // preambles from @vitejs/plugin-react template = await vite.transformIndexHtml(url, template) // 3. Load the server entry. ssrLoadModule automatically transforms // ESM source code to be usable in Node.js! There is no bundling // required, and provides efficient invalidation similar to HMR. const { render } = await vite.ssrLoadModule('/src/entry-server.js') // 4. render the app HTML. This assumes entry-server.js's exported // `render` function calls appropriate framework SSR APIs, // e.g. ReactDOMServer.renderToString() const appHtml = await render(url) // 5. Inject the app-rendered HTML into the template. const html = template.replace(`<!--ssr-outlet-->`, () => appHtml) // 6. Send the rendered HTML back. res.status(200).set({ 'Content-Type': 'text/html' }).end(html) } catch (e) { // If an error is caught, let Vite fix the stack trace so it maps back // to your actual source code. vite.ssrFixStacktrace(e) next(e) } }) The `dev` script in `package.json` should also be changed to use the server script instead: package.json diff "scripts": { - "dev": "vite" + "dev": "node server" } ## Building for Production β To ship an SSR project for production, we need to: 1. Produce a client build as normal; 2. Produce an SSR build, which can be directly loaded via `import()` so that we don't have to go through Vite's `ssrLoadModule`; Our scripts in `package.json` will look like this: package.json json { "scripts": { "dev": "node server", "build:client": "vite build --outDir dist/client", "build:server": "vite build --outDir dist/server --ssr src/entry-server.js" } } Note the `--ssr` flag which indicates this is an SSR build. It should also specify the SSR entry. Then, in `server.js` we need to add some production specific logic by checking `process.env.NODE_ENV`: * Instead of reading the root `index.html`, use the `dist/client/index.html` as the template, since it contains the correct asset links to the client build. * Instead of `await vite.ssrLoadModule('/src/entry-server.js')`, use `import('./dist/server/entry-server.js')` (this file is the result of the SSR build). * Move the creation and all usage of the `vite` dev server behind dev-only conditional branches, then add static file serving middlewares to serve files from `dist/client`. Refer to the example projects for a working setup. ## Generating Preload Directives β `vite build` supports the `--ssrManifest` flag which will generate `.vite/ssr-manifest.json` in build output directory: diff - "build:client": "vite build --outDir dist/client", + "build:client": "vite build --outDir dist/client --ssrManifest", The above script will now generate `dist/client/.vite/ssr-manifest.json` for the client build (Yes, the SSR manifest is generated from the client build because we want to map module IDs to client files). The manifest contains mappings of module IDs to their associated chunks and asset files. To leverage the manifest, frameworks need to provide a way to collect the module IDs of the components that were used during a server render call. `@vitejs/plugin-vue` supports this out of the box and automatically registers used component module IDs on to the associated Vue SSR context: src/entry-server.js js const ctx = {} const html = await vueServerRenderer.renderToString(app, ctx) // ctx.modules is now a Set of module IDs that were used during the render In the production branch of `server.js` we need to read and pass the manifest to the `render` function exported by `src/entry-server.js`. This would provide us with enough information to render preload directives for files used by async routes! See demo source for a full example. You can also use this information for 103 Early Hints. ## Pre-Rendering / SSG β If the routes and the data needed for certain routes are known ahead of time, we can pre-render these routes into static HTML using the same logic as production SSR. This can also be considered a form of Static-Site Generation (SSG). See demo pre-render script for working example. ## SSR Externals β Dependencies are "externalized" from Vite's SSR transform module system by default when running SSR. This speeds up both dev and build. If a dependency needs to be transformed by Vite's pipeline, for example, because Vite features are used untranspiled in them, they can be added to `ssr.noExternal`. For linked dependencies, they are not externalized by default to take advantage of Vite's HMR. If this isn't desired, for example, to test dependencies as if they aren't linked, you can add it to `ssr.external`. Working with Aliases If you have configured aliases that redirect one package to another, you may want to alias the actual `node_modules` packages instead to make it work for SSR externalized dependencies. Both Yarn and pnpm support aliasing via the `npm:` prefix. ## SSR-specific Plugin Logic β Some frameworks such as Vue or Svelte compile components into different formats based on client vs. SSR. To support conditional transforms, Vite passes an additional `ssr` property in the `options` object of the following plugin hooks: * `resolveId` * `load` * `transform` **Example:** js export function mySSRPlugin() { return { name: 'my-ssr', transform(code, id, options) { if (options?.ssr) { // perform ssr-specific transform... } }, } } The options object in `load` and `transform` is optional, rollup is not currently using this object but may extend these hooks with additional metadata in the future. Note Before Vite 2.7, this was informed to plugin hooks with a positional `ssr` param instead of using the `options` object. All major frameworks and plugins are updated but you may find outdated posts using the previous API. ## SSR Target β The default target for the SSR build is a node environment, but you can also run the server in a Web Worker. Packages entry resolution is different for each platform. You can configure the target to be Web Worker using the `ssr.target` set to `'webworker'`. ## SSR Bundle β In some cases like `webworker` runtimes, you might want to bundle your SSR build into a single JavaScript file. You can enable this behavior by setting `ssr.noExternal` to `true`. This will do two things: * Treat all dependencies as `noExternal` * Throw an error if any Node.js built-ins are imported ## SSR Resolve Conditions β By default package entry resolution will use the conditions set in `resolve.conditions` for the SSR build. You can use `ssr.resolve.conditions` and `ssr.resolve.externalConditions` to customize this behavior. ## Vite CLI β The CLI commands `$ vite dev` and `$ vite preview` can also be used for SSR apps. You can add your SSR middlewares to the development server with `configureServer` and to the preview server with `configurePreviewServer`. Note Use a post hook so that your SSR middleware runs _after_ Vite's middlewares. --- ## Page: https://vite.dev/guide/backend-integration # Backend Integration β Note If you want to serve the HTML using a traditional backend (e.g. Rails, Laravel) but use Vite for serving assets, check for existing integrations listed in Awesome Vite. If you need a custom integration, you can follow the steps in this guide to configure it manually 1. In your Vite config, configure the entry and enable build manifest: vite.config.js js export default defineConfig({ server: { cors: { // the origin you will be accessing via browser origin: 'http://my-backend.example.com', }, }, build: { // generate .vite/manifest.json in outDir manifest: true, rollupOptions: { // overwrite default .html entry input: '/path/to/main.js', }, }, }) If you haven't disabled the module preload polyfill, you also need to import the polyfill in your entry js // add the beginning of your app entry import 'vite/modulepreload-polyfill' 2. For development, inject the following in your server's HTML template (substitute `http://localhost:5173` with the local URL Vite is running at): html <!-- if development --> <script type="module" src="http://localhost:5173/@vite/client"></script> <script type="module" src="http://localhost:5173/main.js"></script> In order to properly serve assets, you have two options: * Make sure the server is configured to proxy static assets requests to the Vite server * Set `server.origin` so that generated asset URLs will be resolved using the back-end server URL instead of a relative path This is needed for assets such as images to load properly. Note if you are using React with `@vitejs/plugin-react`, you'll also need to add this before the above scripts, since the plugin is not able to modify the HTML you are serving (substitute `http://localhost:5173` with the local URL Vite is running at): html <script type="module"> import RefreshRuntime from 'http://localhost:5173/@react-refresh' RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type window.__vite_plugin_react_preamble_installed__ = true </script> 3. For production: after running `vite build`, a `.vite/manifest.json` file will be generated alongside other asset files. An example manifest file looks like this: .vite/manifest.json json { "_shared-B7PI925R.js": { "file": "assets/shared-B7PI925R.js", "name": "shared", "css": ["assets/shared-ChJ_j-JJ.css"] }, "_shared-ChJ_j-JJ.css": { "file": "assets/shared-ChJ_j-JJ.css", "src": "_shared-ChJ_j-JJ.css" }, "baz.js": { "file": "assets/baz-B2H3sXNv.js", "name": "baz", "src": "baz.js", "isDynamicEntry": true }, "views/bar.js": { "file": "assets/bar-gkvgaI9m.js", "name": "bar", "src": "views/bar.js", "isEntry": true, "imports": ["_shared-B7PI925R.js"], "dynamicImports": ["baz.js"] }, "views/foo.js": { "file": "assets/foo-BRBmoGS9.js", "name": "foo", "src": "views/foo.js", "isEntry": true, "imports": ["_shared-B7PI925R.js"], "css": ["assets/foo-5UjPuW-k.css"] } } * The manifest has a `Record<name, chunk>` structure * For entry or dynamic entry chunks, the key is the relative src path from project root. * For non entry chunks, the key is the base name of the generated file prefixed with `_`. * For the CSS file generated when `build.cssCodeSplit` is `false`, the key is `style.css`. * Chunks will contain information on its static and dynamic imports (both are keys that map to the corresponding chunk in the manifest), and also its corresponding CSS and asset files (if any). 4. You can use this file to render links or preload directives with hashed filenames. Here is an example HTML template to render the proper links. The syntax here is for explanation only, substitute with your server templating language. The `importedChunks` function is for illustration and isn't provided by Vite. html <!-- if production --> <!-- for cssFile of manifest[name].css --> <link rel="stylesheet" href="/{{ cssFile }}" /> <!-- for chunk of importedChunks(manifest, name) --> <!-- for cssFile of chunk.css --> <link rel="stylesheet" href="/{{ cssFile }}" /> <script type="module" src="/{{ manifest[name].file }}"></script> <!-- for chunk of importedChunks(manifest, name) --> <link rel="modulepreload" href="/{{ chunk.file }}" /> Specifically, a backend generating HTML should include the following tags given a manifest file and an entry point: * A `<link rel="stylesheet">` tag for each file in the entry point chunk's `css` list * Recursively follow all chunks in the entry point's `imports` list and include a `<link rel="stylesheet">` tag for each CSS file of each imported chunk. * A tag for the `file` key of the entry point chunk (`<script type="module">` for JavaScript, or `<link rel="stylesheet">` for CSS) * Optionally, `<link rel="modulepreload">` tag for the `file` of each imported JavaScript chunk, again recursively following the imports starting from the entry point chunk. Following the above example manifest, for the entry point `views/foo.js` the following tags should be included in production: html <link rel="stylesheet" href="assets/foo-5UjPuW-k.css" /> <link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" /> <script type="module" src="assets/foo-BRBmoGS9.js"></script> <!-- optional --> <link rel="modulepreload" href="assets/shared-B7PI925R.js" /> While the following should be included for the entry point `views/bar.js`: html <link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" /> <script type="module" src="assets/bar-gkvgaI9m.js"></script> <!-- optional --> <link rel="modulepreload" href="assets/shared-B7PI925R.js" /> Pseudo implementation of `importedChunks` An example pseudo implementation of `importedChunks` in TypeScript (This will need to be adapted for your programming language and templating language): ts import type { Manifest, ManifestChunk } from 'vite' export default function importedChunks( manifest: Manifest, name: string, ): ManifestChunk[] { const seen = new Set<string>() function getImportedChunks(chunk: ManifestChunk): ManifestChunk[] { const chunks: ManifestChunk[] = [] for (const file of chunk.imports ?? []) { const importee = manifest[file] if (seen.has(file)) { continue } seen.add(file) chunks.push(...getImportedChunks(importee)) chunks.push(importee) } return chunks } return getImportedChunks(manifest[name]) } --- ## Page: https://vite.dev/guide/troubleshooting # Troubleshooting β See Rollup's troubleshooting guide for more information too. If the suggestions here don't work, please try posting questions on GitHub Discussions or in the `#help` channel of Vite Land Discord. ## CJS β ### Vite CJS Node API deprecated β The CJS build of Vite's Node API is deprecated and will be removed in Vite 6. See the GitHub discussion for more context. You should update your files or frameworks to import the ESM build of Vite instead. In a basic Vite project, make sure: 1. The `vite.config.js` file content is using the ESM syntax. 2. The closest `package.json` file has `"type": "module"`, or use the `.mjs`/`.mts` extension, e.g. `vite.config.mjs` or `vite.config.mts`. For other projects, there are a few general approaches: * **Configure ESM as default, opt-in to CJS if needed:** Add `"type": "module"` in the project `package.json`. All `*.js` files are now interpreted as ESM and need to use the ESM syntax. You can rename a file with the `.cjs` extension to keep using CJS instead. * **Keep CJS as default, opt-in to ESM if needed:** If the project `package.json` does not have `"type": "module"`, all `*.js` files are interpreted as CJS. You can rename a file with the `.mjs` extension to use ESM instead. * **Dynamically import Vite:** If you need to keep using CJS, you can dynamically import Vite using `import('vite')` instead. This requires your code to be written in an `async` context, but should still be manageable as Vite's API is mostly asynchronous. If you're unsure where the warning is coming from, you can run your script with the `VITE_CJS_TRACE=true` flag to log the stack trace: bash VITE_CJS_TRACE=true vite dev If you'd like to temporarily ignore the warning, you can run your script with the `VITE_CJS_IGNORE_WARNING=true` flag: bash VITE_CJS_IGNORE_WARNING=true vite dev Note that postcss config files do not support ESM + TypeScript (`.mts` or `.ts` in `"type": "module"`) yet. If you have postcss configs with `.ts` and added `"type": "module"` to package.json, you'll also need to rename the postcss config to use `.cts`. ## CLI β ### `Error: Cannot find module 'C:\foo\bar&baz\vite\bin\vite.js'` β The path to your project folder may include `&`, which doesn't work with `npm` on Windows (npm/cmd-shim#45). You will need to either: * Switch to another package manager (e.g. `pnpm`, `yarn`) * Remove `&` from the path to your project ## Config β ### This package is ESM only β When importing a ESM only package by `require`, the following error happens. > Failed to resolve "foo". This package is ESM only but it was tried to load by `require`. > Error \[ERR\_REQUIRE\_ESM\]: require() of ES Module /path/to/dependency.js from /path/to/vite.config.js not supported. Instead change the require of index.js in /path/to/vite.config.js to a dynamic import() which is available in all CommonJS modules. In Node.js <=22, ESM files cannot be loaded by `require` by default. While it may work using `--experimental-require-module`, or Node.js >22, or in other runtimes, we still recommend converting your config to ESM by either: * adding `"type": "module"` to the nearest `package.json` * renaming `vite.config.js`/`vite.config.ts` to `vite.config.mjs`/`vite.config.mts` ### `failed to load config from '/path/to/config*/vite.config.js'` β > failed to load config from '/path/to/config\*/vite.config.js' error when starting dev server: Error: Build failed with 1 error: error: Must use "outdir" when there are multiple input files The error above may occur if the path to your project folder contains `*`, which esbuild treats as a glob. You will need to rename your directory to remove the `*`. ## Dev Server β ### Requests are stalled forever β If you are using Linux, file descriptor limits and inotify limits may be causing the issue. As Vite does not bundle most of the files, browsers may request many files which require many file descriptors, going over the limit. To solve this: * Increase file descriptor limit by `ulimit` shell # Check current limit $ ulimit -Sn # Change limit (temporary) $ ulimit -Sn 10000 # You might need to change the hard limit too # Restart your browser * Increase the following inotify related limits by `sysctl` shell # Check current limits $ sysctl fs.inotify # Change limits (temporary) $ sudo sysctl fs.inotify.max_queued_events=16384 $ sudo sysctl fs.inotify.max_user_instances=8192 $ sudo sysctl fs.inotify.max_user_watches=524288 If the above steps don't work, you can try adding `DefaultLimitNOFILE=65536` as an un-commented config to the following files: * /etc/systemd/system.conf * /etc/systemd/user.conf For Ubuntu Linux, you may need to add the line `* - nofile 65536` to the file `/etc/security/limits.conf` instead of updating systemd config files. Note that these settings persist but a **restart is required**. Alternatively, if the server is running inside a VS Code devcontainer, the request may appear to be stalled. To fix this issue, see Dev Containers / VS Code Port Forwarding. ### Network requests stop loading β When using a self-signed SSL certificate, Chrome ignores all caching directives and reloads the content. Vite relies on these caching directives. To resolve the problem use a trusted SSL cert. See: Cache problems, Chrome issue #### macOS β You can install a trusted cert via the CLI with this command: security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain-db your-cert.cer Or, by importing it into the Keychain Access app and updating the trust of your cert to "Always Trust." ### 431 Request Header Fields Too Large β When the server / WebSocket server receives a large HTTP header, the request will be dropped and the following warning will be shown. > Server responded with status code 431. See https://vite.dev/guide/troubleshooting.html#\_431-request-header-fields-too-large. This is because Node.js limits request header size to mitigate CVE-2018-12121. To avoid this, try to reduce your request header size. For example, if the cookie is long, delete it. Or you can use `--max-http-header-size` to change max header size. ### Dev Containers / VS Code Port Forwarding β If you are using a Dev Container or port forwarding feature in VS Code, you may need to set the `server.host` option to `127.0.0.1` in the config to make it work. This is because the port forwarding feature in VS Code does not support IPv6. See #16522 for more details. ## HMR β ### Vite detects a file change but the HMR is not working β You may be importing a file with a different case. For example, `src/foo.js` exists and `src/bar.js` contains: js import './Foo.js' // should be './foo.js' Related issue: #964 ### Vite does not detect a file change β If you are running Vite with WSL2, Vite cannot watch file changes in some conditions. See `server.watch` option. ### A full reload happens instead of HMR β If HMR is not handled by Vite or a plugin, a full reload will happen as it's the only way to refresh the state. If HMR is handled but it is within a circular dependency, a full reload will also happen to recover the execution order. To solve this, try breaking the loop. You can run `vite --debug hmr` to log the circular dependency path if a file change triggered it. ## Build β ### Built file does not work because of CORS error β If the HTML file output was opened with `file` protocol, the scripts won't run with the following error. > Access to script at 'file:///foo/bar.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted. > Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///foo/bar.js. (Reason: CORS request not http). See Reason: CORS request not HTTP - HTTP | MDN for more information about why this happens. You will need to access the file with `http` protocol. The easiest way to achieve this is to run `npx vite preview`. ## Optimized Dependencies β ### Outdated pre-bundled deps when linking to a local package β The hash key used to invalidate optimized dependencies depends on the package lock contents, the patches applied to dependencies, and the options in the Vite config file that affects the bundling of node modules. This means that Vite will detect when a dependency is overridden using a feature as npm overrides, and re-bundle your dependencies on the next server start. Vite won't invalidate the dependencies when you use a feature like npm link. In case you link or unlink a dependency, you'll need to force re-optimization on the next server start by using `vite --force`. We recommend using overrides instead, which are supported now by every package manager (see also pnpm overrides and yarn resolutions). ## Performance Bottlenecks β If you suffer any application performance bottlenecks resulting in slow load times, you can start the built-in Node.js inspector with your Vite dev server or when building your application to create the CPU profile: dev serverbuild bash vite --profile --open bash vite build --profile Vite Dev Server Once your application is opened in the browser, just await finish loading it and then go back to the terminal and press `p` key (will stop the Node.js inspector) then press `q` key to stop the dev server. Node.js inspector will generate `vite-profile-0.cpuprofile` in the root folder, go to https://www.speedscope.app/, and upload the CPU profile using the `BROWSE` button to inspect the result. You can install vite-plugin-inspect, which lets you inspect the intermediate state of Vite plugins and can also help you to identify which plugins or middlewares are the bottleneck in your applications. The plugin can be used in both dev and build modes. Check the readme file for more details. ## Others β ### Module externalized for browser compatibility β When you use a Node.js module in the browser, Vite will output the following warning. > Module "fs" has been externalized for browser compatibility. Cannot access "fs.readFile" in client code. This is because Vite does not automatically polyfill Node.js modules. We recommend avoiding Node.js modules for browser code to reduce the bundle size, although you can add polyfills manually. If the module is imported from a third-party library (that's meant to be used in the browser), it's advised to report the issue to the respective library. ### Syntax Error / Type Error happens β Vite cannot handle and does not support code that only runs on non-strict mode (sloppy mode). This is because Vite uses ESM and it is always strict mode inside ESM. For example, you might see these errors. > \[ERROR\] With statements cannot be used with the "esm" output format due to strict mode > TypeError: Cannot create property 'foo' on boolean 'false' If these codes are used inside dependencies, you could use `patch-package` (or `yarn patch` or `pnpm patch`) for an escape hatch. ### Browser extensions β Some browser extensions (like ad-blockers) may prevent the Vite client from sending requests to the Vite dev server. You may see a white screen without logged errors in this case. Try disabling extensions if you have this issue. ### Cross drive links on Windows β If there's a cross drive links in your project on Windows, Vite may not work. An example of cross drive links are: * a virtual drive linked to a folder by `subst` command * a symlink/junction to a different drive by `mklink` command (e.g. Yarn global cache) Related issue: #10802 --- ## Page: https://vite.dev/guide/performance # Performance β While Vite is fast by default, performance issues can creep in as the project's requirements grow. This guide aims to help you identify and fix common performance issues, such as: * Slow server starts * Slow page loads * Slow builds ## Review your Browser Setup β Some browser extensions may interfere with requests and slow down startup and reload times for large apps, especially when using browser dev tools. We recommend creating a dev-only profile without extensions, or switch to incognito mode, while using Vite's dev server in these cases. Incognito mode should also be faster than a regular profile without extensions. The Vite dev server does hard caching of pre-bundled dependencies and implements fast 304 responses for source code. Disabling the cache while the Browser Dev Tools are open can have a big impact on startup and full-page reload times. Please check that "Disable Cache" isn't enabled while you work with the Vite server. ## Audit Configured Vite Plugins β Vite's internal and official plugins are optimized to do the least amount of work possible while providing compatibility with the broader ecosystem. For example, code transformations use regex in dev, but do a complete parse in build to ensure correctness. However, the performance of community plugins is out of Vite's control, which may affect the developer experience. Here are a few things you can look out for when using additional Vite plugins: 1. Large dependencies that are only used in certain cases should be dynamically imported to reduce the Node.js startup time. Example refactors: vite-plugin-react#212 and vite-plugin-pwa#224. 2. The `buildStart`, `config`, and `configResolved` hooks should not run long and extensive operations. These hooks are awaited during dev server startup, which delays when you can access the site in the browser. 3. The `resolveId`, `load`, and `transform` hooks may cause some files to load slower than others. While sometimes unavoidable, it's still worth checking for possible areas to optimize. For example, checking if the `code` contains a specific keyword, or the `id` matches a specific extension, before doing the full transformation. The longer it takes to transform a file, the more significant the request waterfall will be when loading the site in the browser. You can inspect the duration it takes to transform a file using `vite --debug plugin-transform` or vite-plugin-inspect. Note that as asynchronous operations tend to provide inaccurate timings, you should treat the numbers as a rough estimate, but it should still reveal the more expensive operations. Profiling You can run `vite --profile`, visit the site, and press `p + enter` in your terminal to record a `.cpuprofile`. A tool like speedscope can then be used to inspect the profile and identify the bottlenecks. You can also share the profiles with the Vite team to help us identify performance issues. ## Reduce Resolve Operations β Resolving import paths can be an expensive operation when hitting its worst case often. For example, Vite supports "guessing" import paths with the `resolve.extensions` option, which defaults to `['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']`. When you try to import `./Component.jsx` with `import './Component'`, Vite will run these steps to resolve it: 1. Check if `./Component` exists, no. 2. Check if `./Component.mjs` exists, no. 3. Check if `./Component.js` exists, no. 4. Check if `./Component.mts` exists, no. 5. Check if `./Component.ts` exists, no. 6. Check if `./Component.jsx` exists, yes! As shown, a total of 6 filesystem checks is required to resolve an import path. The more implicit imports you have, the more time it adds up to resolve the paths. Hence, it's usually better to be explicit with your import paths, e.g. `import './Component.jsx'`. You can also narrow down the list for `resolve.extensions` to reduce the general filesystem checks, but you have to make sure it works for files in `node_modules` too. If you're a plugin author, make sure to only call `this.resolve` when needed to reduce the number of checks above. TypeScript If you are using TypeScript, enable `"moduleResolution": "bundler"` and `"allowImportingTsExtensions": true` in your `tsconfig.json`'s `compilerOptions` to use `.ts` and `.tsx` extensions directly in your code. ## Avoid Barrel Files β Barrel files are files that re-export the APIs of other files in the same directory. For example: src/utils/index.js js export * from './color.js' export * from './dom.js' export * from './slash.js' When you only import an individual API, e.g. `import { slash } from './utils'`, all the files in that barrel file need to be fetched and transformed as they may contain the `slash` API and may also contain side-effects that run on initialization. This means you're loading more files than required on the initial page load, resulting in a slower page load. If possible, you should avoid barrel files and import the individual APIs directly, e.g. `import { slash } from './utils/slash.js'`. You can read issue #8237 for more information. ## Warm Up Frequently Used Files β The Vite dev server only transforms files as requested by the browser, which allows it to start up quickly and only apply transformations for used files. It can also pre-transform files if it anticipates certain files will be requested shortly. However, request waterfalls may still happen if some files take longer to transform than others. For example: Given an import graph where the left file imports the right file: main.js -> BigComponent.vue -> big-utils.js -> large-data.json The import relationship can only be known after the file is transformed. If `BigComponent.vue` takes some time to transform, `big-utils.js` has to wait for its turn, and so on. This causes an internal waterfall even with pre-transformation built-in. Vite allows you to warm up files that you know are frequently used, e.g. `big-utils.js`, using the `server.warmup` option. This way `big-utils.js` will be ready and cached to be served immediately when requested. You can find files that are frequently used by running `vite --debug transform` and inspect the logs: bash vite:transform 28.72ms /@vite/client +1ms vite:transform 62.95ms /src/components/BigComponent.vue +1ms vite:transform 102.54ms /src/utils/big-utils.js +1ms vite.config.js js export default defineConfig({ server: { warmup: { clientFiles: [ './src/components/BigComponent.vue', './src/utils/big-utils.js', ], }, }, }) Note that you should only warm up files that are frequently used to not overload the Vite dev server on startup. Check the `server.warmup` option for more information. Using `--open` or `server.open` also provides a performance boost, as Vite will automatically warm up the entry point of your app or the provided URL to open. ## Use Lesser or Native Tooling β Keeping Vite fast with a growing codebase is about reducing the amount of work for the source files (JS/TS/CSS). Examples of doing less work: * Use CSS instead of Sass/Less/Stylus when possible (nesting can be handled by PostCSS) * Don't transform SVGs into UI framework components (React, Vue, etc). Import them as strings or URLs instead. * When using `@vitejs/plugin-react`, avoid configuring the Babel options, so it skips the transformation during build (only esbuild will be used). Examples of using native tooling: Using native tooling often brings larger installation size and as so is not the default when starting a new Vite project. But it may be worth the cost for larger applications. * Try out the experimental support for LightningCSS * Use `@vitejs/plugin-react-swc` in place of `@vitejs/plugin-react`. --- ## Page: https://vite.dev/guide/migration # Migration from v5 β ## Environment API β As part of the new experimental Environment API, a big internal refactoring was needed. Vite 6 strives to avoid breaking changes to ensure most projects can quickly upgrade to the new major. We'll wait until a big portion of the ecosystem has moved to stabilize and start recommending the use of the new APIs. There may be some edge cases but these should only affect low level usage by frameworks and tools. We have worked with maintainers in the ecosystem to mitigate these differences before the release. Please open an issue if you spot a regression. Some internal APIs have been removed due to changes in Vite's implementation. If you were relying on one of them, please create a feature request. ## Vite Runtime API β The experimental Vite Runtime API evolved into the Module Runner API, released in Vite 6 as part of the new experimental Environment API. Given that the feature was experimental the removal of the previous API introduced in Vite 5.1 isn't a breaking change, but users will need to update their use to the Module Runner equivalent as part of migrating to Vite 6. ## General Changes β ### Default value for `resolve.conditions` β This change does not affect users that did not configure `resolve.conditions` / `ssr.resolve.conditions` / `ssr.resolve.externalConditions`. In Vite 5, the default value for `resolve.conditions` was `[]` and some conditions were added internally. The default value for `ssr.resolve.conditions` was the value of `resolve.conditions`. From Vite 6, some of the conditions are no longer added internally and need to be included in the config values. The conditions that are no longer added internally for * `resolve.conditions` are `['module', 'browser', 'development|production']` * `ssr.resolve.conditions` are `['module', 'node', 'development|production']` The default values for those options are updated to the corresponding values and `ssr.resolve.conditions` no longer uses `resolve.conditions` as the default value. Note that `development|production` is a special variable that is replaced with `production` or `development` depending on the value of `process.env.NODE_ENV`. These default values are exported from `vite` as `defaultClientConditions` and `defaultServerConditions`. If you specified a custom value for `resolve.conditions` or `ssr.resolve.conditions`, you need to update it to include the new conditions. For example, if you previously specified `['custom']` for `resolve.conditions`, you need to specify `['custom', ...defaultClientConditions]` instead. ### JSON stringify β In Vite 5, when `json.stringify: true` is set, `json.namedExports` was disabled. From Vite 6, even when `json.stringify: true` is set, `json.namedExports` is not disabled and the value is respected. If you wish to achieve the previous behavior, you can set `json.namedExports: false`. Vite 6 also introduces a new default value for `json.stringify` which is `'auto'`, which will only stringify large JSON files. To disable this behavior, set `json.stringify: false`. ### Extended support of asset references in HTML elements β In Vite 5, only a few supported HTML elements were able to reference assets that will be processed and bundled by Vite, such as `<link href>`, `<img src>`, etc. Vite 6 extends the support to even more HTML elements. The full list can be found at the HTML features docs. To opt-out of HTML processing on certain elements, you can add the `vite-ignore` attribute on the element. ### postcss-load-config β `postcss-load-config` has been updated to v6 from v4. `tsx` or `jiti` is now required to load TypeScript postcss config files instead of `ts-node`. Also `yaml` is now required to load YAML postcss config files. ### Sass now uses modern API by default β In Vite 5, the legacy API was used by default for Sass. Vite 5.4 added support for the modern API. From Vite 6, the modern API is used by default for Sass. If you wish to still use the legacy API, you can set `css.preprocessorOptions.sass.api: 'legacy'` / `css.preprocessorOptions.scss.api: 'legacy'`. But note that the legacy API support will be removed in Vite 7. To migrate to the modern API, see the Sass documentation. ### Customize CSS output file name in library mode β In Vite 5, the CSS output file name in library mode was always `style.css` and cannot be easily changed through the Vite config. From Vite 6, the default file name now uses `"name"` in `package.json` similar to the JS output files. If `build.lib.fileName` is set with a string, the value will also be used for the CSS output file name. To explicitly set a different CSS file name, you can use the new `build.lib.cssFileName` to configure it. To migrate, if you had relied on the `style.css` file name, you should update references to it to the new name based on your package name. For example: package.json json { "name": "my-lib", "exports": { "./style.css": "./dist/style.css" "./style.css": "./dist/my-lib.css" } } If you prefer to stick with `style.css` like in Vite 5, you can set `build.lib.cssFileName: 'style'` instead. ## Advanced β There are other breaking changes which only affect few users. * \[#17922\] fix(css)!: remove default import in ssr dev * Support for default import of CSS files was deprecated in Vite 4 and removed in Vite 5, but it was still unintentionally supported in SSR dev mode. This support is now removed. * \[#15637\] fix!: default `build.cssMinify` to `'esbuild'` for SSR * `build.cssMinify` is now enabled by default even for SSR builds. * \[#18070\] feat!: proxy bypass with WebSocket * `server.proxy[path].bypass` is now called for WebSocket upgrade requests and in that case, the `res` parameter will be `undefined`. * \[#18209\] refactor!: bump minimal terser version to 5.16.0 * Minimal supported terser version for `build.minify: 'terser'` was bumped to 5.16.0 from 5.4.0. * \[#18231\] chore(deps): update dependency @rollup/plugin-commonjs to v28 * `commonjsOptions.strictRequires` is now `true` by default (was `'auto'` before). * This may lead to larger bundle sizes but will result in more deterministic builds. * If you are specifying a CommonJS file as an entry point, you may need additional steps. Read the commonjs plugin documentation for more details. * \[#18243\] chore(deps)!: migrate `fast-glob` to `tinyglobby` * Range braces (`{01..03}` β `['01', '02', '03']`) and incremental braces (`{2..8..2}` β `['2', '4', '6', '8']`) are no longer supported in globs. * \[#18395\] feat(resolve)!: allow removing conditions * This PR not only introduces a breaking change mentioned above as "Default value for `resolve.conditions`", but also makes `resolve.mainFields` to not be used for no-externalized dependencies in SSR. If you were using `resolve.mainFields` and want to apply that to no-externalized dependencies in SSR, you can use `ssr.resolve.mainFields`. * \[#18493\] refactor!: remove fs.cachedChecks option * This opt-in optimization was removed due to edge cases when writing a file in a cached folder and immediately importing it. * ~\[#18697\] fix(deps)!: update dependency dotenv-expand to v12~ * ~Variables used in interpolation should be declared before the interpolation now. For more details, see the `dotenv-expand` changelog.~ This breaking change was reverted in v6.1.0. * \[#16471\] feat: v6 - Environment API * Updates to an SSR-only module no longer triggers a full page reload in the client. To return to the previous behaviour, a custom Vite plugin can be used: Click to expand example ts import type { Plugin, EnvironmentModuleNode } from 'vite' function hmrReload(): Plugin { return { name: 'hmr-reload', enforce: 'post', hotUpdate: { order: 'post', handler({ modules, server, timestamp }) { if (this.environment.name !== 'ssr') return let hasSsrOnlyModules = false const invalidatedModules = new Set<EnvironmentModuleNode>() for (const mod of modules) { if (mod.id == null) continue const clientModule = server.environments.client.moduleGraph.getModuleById(mod.id) if (clientModule != null) continue this.environment.moduleGraph.invalidateModule( mod, invalidatedModules, timestamp, true, ) hasSsrOnlyModules = true } if (hasSsrOnlyModules) { server.ws.send({ type: 'full-reload' }) return [] } }, }, } } ## Migration from v4 β Check the Migration from v4 Guide in the Vite v5 docs first to see the needed changes to port your app to Vite 5, and then proceed with the changes on this page.