Production build browser support targets Baseline Widely Available
Vite by default targets Baseline Widely Available browser versions as of a date fixed for each major release. For the current major, this corresponds to browser versions released around mid-2023.
Development browser support targets esnext
During development, Vite assumes a modern browser is used and sets esnext as the transform target. This prevents syntax lowering and lets Vite serve modules as close as possible to the original source code.
Vite 8 uses Rolldown instead of Rollup and esbuild
Vite 8 has migrated from esbuild and Rollup to Rolldown and Oxc based tools. The dependency optimizer now uses Rolldown instead of esbuild, JavaScript transformation uses Oxc instead of esbuild, and JavaScript minification uses the Oxc Minifier instead of esbuild.
esbuild option deprecated in favor of oxc
The esbuild configuration option is now deprecated in Vite 8. Users should migrate to the oxc option. Vite automatically converts esbuild to oxc for backward compatibility, but this will be removed in the future.
esbuild to oxc automatic conversions
Vite 8 automatically converts these esbuild options to oxc: esbuild.jsxInject to oxc.jsxInject; esbuild.include to oxc.include; esbuild.exclude to oxc.exclude; esbuild.jsx to oxc.jsx (with special handling: 'preserve' stays 'preserve', 'automatic' becomes { runtime: 'automatic' }, 'transform' becomes { runtime: 'classic' }); esbuild.jsxImportSource to oxc.jsx.importSource; esbuild.jsxFactory to oxc.jsx.pragma; esbuild.jsxFragment to oxc.jsx.pragmaFrag; esbuild.jsxDev to oxc.jsx.development; esbuild.jsxSideEffects to oxc.jsx.pure; esbuild.define to oxc.define.
esbuild.banner and esbuild.footer migration to Oxc
The esbuild.banner and esbuild.footer options are not directly supported by Oxc. To achieve the same functionality in Vite 8, use a custom plugin with the transform hook instead.
Oxc does not support native decorators lowering
The Oxc transformer in Vite 8 does not support lowering native decorators. Users can work around this by using Babel or SWC plugins instead.
transformWithEsbuild is deprecated, use transformWithOxc
The transformWithEsbuild function is deprecated in Vite 8 and will be removed in the future. Users should migrate to the transformWithOxc function instead. If using a plugin that calls transformWithEsbuild, install esbuild as a devDependency since Vite no longer relies on esbuild directly.
build.minify esbuild option deprecated
The build.minify: 'esbuild' option is deprecated in Vite 8. If you need to switch back to esbuild minification, you must install esbuild as a devDependency. This configuration option will be removed in the future.
Oxc minification controls and limitations
In Vite 8, JavaScript minification is performed by Oxc. If you were using esbuild.minify* options, use build.rolldownOptions.output.minify instead. If using esbuild.drop option, use build.rolldownOptions.output.minify.compress.drop* options. Property mangling options (mangleProps, reserveProps, mangleQuoted, mangleCache) are not supported by Oxc.
CSS minification by Lightning CSS
Lightning CSS is now used for CSS minification by default in Vite 8. To switch back to esbuild CSS minification, use the build.cssMinify: 'esbuild' option and install esbuild as a devDependency. Lightning CSS supports better syntax lowering, though CSS bundle size might increase slightly.
import.meta.url no longer polyfilled in UMD/IIFE
In Vite 8, import.meta.url is no longer polyfilled in UMD and IIFE output formats. It will be replaced with undefined by default. To restore the previous behavior, use the define option with build.rolldownOptions.output.intro option.
build.rollupOptions.watch.chokidar removed
The build.rollupOptions.watch.chokidar option has been removed in Vite 8. Migrate to the build.rolldownOptions.watch.watcher option instead.
build.rollupOptions.output.manualChunks deprecated
The object form of build.rollupOptions.output.manualChunks is no longer supported in Vite 8. The function form is deprecated. Use Rolldown's more flexible codeSplitting option instead.
TypeScript namespace partial support in Oxc
Oxc transformer in Vite 8 has only partial support for TypeScript legacy namespaces. For details, see Oxc Transformer's related documentation.
Rolldown unsupported output formats
Vite 8 no longer supports build.rollupOptions.output.format: 'system' or 'amd' because Rolldown does not support these formats.
define object reference behavior in Oxc
In Vite 8, when passing an object as a value to define, each variable will have a separate copy of the object rather than sharing the same reference. This differs from previous behavior.
Vite 8 default browser target versions
Vite 8 updates the default browser values of build.target to align with Baseline Widely Available features as of 2026-01-01. The new defaults are: Chrome 111 (from 107), Edge 111 (from 107), Firefox 114 (from 104), Safari 16.4 (from 16.0). These browser versions were all released approximately two and a half years ago.
TypeScript transpilation without type checking
Vite only performs transpilation on .ts files and does NOT perform type checking. It assumes type checking is taken care of by the IDE and build process. Vite uses Oxc Transformer to transpile TypeScript into JavaScript, which is faster than vanilla tsc, and HMR updates can reflect in the browser in under 50ms.
Custom JSX configuration
If using JSX with a custom framework, custom `jsxFactory` and `jsxFragment` can be configured using the `oxc` option. Example: `oxc: { jsx: { importSource: 'preact' } }`. You can inject JSX helpers using `jsxInject` (a Vite-only option) to avoid manual imports: `oxc: { jsxInject: `import React from 'react'` }`.
TypeScript declaration for .wasm files
To enable TypeScript support for `.wasm` files, enable `allowArbitraryExtensions` in tsconfig.json and create a declaration file next to the `.wasm` file named `{filename}.d.wasm.ts`. For example, for `add.wasm`, create `add.d.wasm.ts` with the exported functions declared.
Type-only imports syntax
Use the Type-Only Imports and Export syntax to avoid potential problems like type-only imports being incorrectly bundled. Example: `import type { T } from 'only/types'` and `export type { T }`.
tsconfig.json isolatedModules must be true
The `isolatedModules` option in tsconfig.json compilerOptions must be set to `true`. This is because Oxc transformer only performs transpilation without type information and doesn't support certain features like const enum and implicit type-only imports. TS will warn against features that do not work with isolated transpilation.
tsconfig.json useDefineForClassFields default value
The default value of `useDefineForClassFields` will be `true` if the TypeScript target is `ES2022` or newer including `ESNext`. For other TypeScript targets it defaults to `false`. `true` is the standard ECMAScript runtime behavior.
Vite ignores tsconfig.json target option
Vite ignores the `target` value in tsconfig.json, following the same behavior as esbuild. To specify the target in dev, use the `oxc.target` option which defaults to `esnext` for minimal transpilation. In builds, the `build.target` option takes higher priority over `oxc.target`.
Client types configuration
To shim the environment of client-side code in a Vite application, add `vite/client` to `compilerOptions.types` inside tsconfig.json. Note that if `compilerOptions.types` is specified, only these packages will be included in the global scope. Alternatively, you can add a d.ts declaration file with `/// <reference types="vite/client" />`.
vite/client type shims
`vite/client` provides type shims for: asset imports (e.g. importing an .svg file), types for the Vite-injected constants on `import.meta.env`, and types for the HMR API on `import.meta.hot`.
HTML files as entry points
HTML files stand front-and-center of a Vite project, serving as the entry points for the application. Any HTML files in the project root can be directly accessed by their 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`.
CSS code splitting in builds
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. This can be disabled 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
Vite automatically rewrites code-split dynamic import calls with a preload step so that when an async chunk is requested, its dependencies are fetched in parallel rather than sequentially. Vite traces all the direct imports to completely eliminate roundtrips regardless of import depth.
Chunk import map optimization
To improve the cache hit rate of chunks and prevent cascading cache invalidation, Vite can create an import map for chunks. When enabled via `build.chunkImportMap: true`, Vite uses chunk IDs in import statements instead of URLs. This way, when a chunk is updated, only that chunk needs to be invalidated, while chunks that reference it will not be invalidated. This optimization currently does not apply to CSS and assets.
Content Security Policy nonce
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, Vite will inject a meta tag (`<meta property="csp-nonce" nonce="PLACEHOLDER" />`). The nonce value of this meta tag will be used by Vite whenever necessary during both dev and after build. Ensure that you replace the placeholder with a unique value for each request.
CSP data: URI for inlined assets
By default, during build, Vite inlines small assets as data URIs. Allowing `data:` for related directives (e.g. `img-src`, `font-src`) is necessary, or disable inlining by setting `build.assetsInlineLimit: 0`. Do not allow `data:` for `script-src` as it will allow injection of arbitrary scripts.
Build licenses generation
Vite can generate a file of all the dependencies' licenses used in the build with the `build.license` option set to `true`. This generates a `.vite/license.md` file listing all licenses. To serve the file at a different path, pass `{ fileName: 'license.md' }` to the option.
JSX files support
`.jsx` and `.tsx` files are supported out of the box. JSX transpilation is handled via Oxc Transformer. Your framework of choice will already configure JSX out of the box (e.g., Vue users should use the official @vitejs/plugin-vue-jsx plugin, React users should use @vitejs/plugin-react).
Vite uses Rolldown bundler
Vite's bundler is Rolldown, which maintains compatibility with Rollup's plugin interface.
Vite leverages Oxc and Rolldown for intensive tasks
Vite is based on native tools that include the Oxc toolchain and Rolldown to implement intensive tasks, while keeping the rest of the code in JavaScript to balance speed with flexibility.
Firebase hosting configuration
For Firebase deployment, create a `firebase.json` file with hosting configuration pointing to the `dist` directory as public, and configure rewrites so all routes redirect to `/index.html` for single-page application routing.
Default build output directory
The default build output location is `dist`. This location can be changed using `build.outDir` configuration option.
GitHub Pages base configuration
When deploying to GitHub Pages, set the `base` option in `vite.config.js`. If deploying to `https://<USERNAME>.github.io/` or a custom domain, set `base` to `'/'` or omit it as it defaults to `'/'`. If deploying to `https://<USERNAME>.github.io/<REPO>/`, set `base` to `'/<REPO>/'`.
GitLab Pages base configuration
When deploying to GitLab Pages, set the `base` option in `vite.config.js`. If deploying to `https://<USERNAME or GROUP>.gitlab.io/`, omit `base` as it defaults to `'/'`. If deploying to `https://<USERNAME or GROUP>.gitlab.io/<REPO>/`, set `base` to `'/<REPO>/'`.
Cloudflare Workers Vite plugin setup
To add Cloudflare Workers to a Vite project, install the plugin with `npm install --save-dev @cloudflare/vite-plugin`, then add `import { cloudflare } from '@cloudflare/vite-plugin'` and include `plugins: [cloudflare()]` in the Vite config. Create a `wrangler.jsonc` file with at least a `name` property. Deploy after building with `npx wrangler deploy`.
Why production builds still require bundling
Although unbundled ESM works well during development, shipping it in production is still inefficient due to additional network round trips from nested imports, which is why bundling is still necessary for optimized production builds.
Vite's original dual-tool architecture and its limitations
Vite originally relied on esbuild for fast compilation during development and Rollup for thorough optimization in production builds. While this worked, maintaining two pipelines introduced inconsistencies: different transformation behaviors, separate plugin systems, and growing glue code to keep them aligned.
Rolldown's role in unifying Vite's toolchain
Rolldown was built to unify esbuild and Rollup into a single bundler written in Rust for native speed, compatible with the same plugin API the ecosystem already relied on. It uses Oxc for parsing, transforming, and minifying, giving Vite an end-to-end toolchain where the build tool, bundler, and compiler are maintained together and evolve as a unit.
HTML opened with file protocol causes CORS error in built output
If a built HTML file is opened with the file:// protocol, the scripts will not run due to CORS policy restrictions that only allow http, data, isolated-app, chrome-extension, chrome, https, and chrome-untrusted protocols. To fix this, access the file with http protocol by running npx vite preview.
Case sensitivity errors when building on case-sensitive filesystem
When a project developed on a case-insensitive filesystem (Windows/macOS) is built on a case-sensitive one (Linux), errors like ENOENT or Module not found occur. Ensure that all imports have the correct casing.
Failed to fetch dynamically imported module error causes
The error "TypeError: Failed to fetch dynamically imported module" occurs due to version skew, poor network conditions, or browser extensions blocking requests. Version skew happens when users have an old cached version of the app and you deploy a new version with different chunk names that no longer exist. Solutions include keeping old chunks temporarily, using a service worker to cache assets, prefetching dynamic chunks, or implementing graceful fallback error handling. Poor network conditions or unstable environments may cause fetch failures, but retrying is not possible due to browser limitations. Browser extensions like ad-blockers may block requests.
Dynamic import chunk name selection to avoid ad-blocker blocking
If browser extensions (like ad-blockers) are blocking dynamic imports, you can work around this by selecting a different chunk name using build.rolldownOptions.output.chunkFileNames, since these extensions often block requests based on file names (e.g., names containing 'ad' or 'track').
Relative base path configuration
Setting `base` to "./" or "" makes all generated URLs relative to each file. This requires import.meta support; browsers that do not support import.meta need the legacy plugin.
Customizing build with rolldownOptions
The build can be customized via `build.rolldownOptions` to directly adjust the underlying Rolldown options, including specifying multiple Rolldown outputs with plugins applied only during build.
Code splitting configuration
Code splitting can be configured using `build.rolldownOptions.output.codeSplitting` according to Rolldown docs for manual code splitting.
vite:preloadError event for failed dynamic imports
Vite emits a `vite:preloadError` event when it fails to load dynamic imports. The `event.payload` contains the original import error. Calling `event.preventDefault()` prevents the error from being thrown.
Handling stale assets after deployment
When a new deployment deletes assets from previous deployments, users with cached old assets encounter import errors. The `vite:preloadError` event is useful for addressing this. Set `Cache-Control: no-cache` on the HTML file to prevent old assets from being cached.
Watch mode for rebuild on file changes
Enable Rolldown watcher with `vite build --watch` to rebuild when bundled files change. Adjust underlying WatcherOptions via `build.watch`. Changes to config and its dependencies require restarting the build command.
import.meta.dirname in multi-page configs
When using `import.meta.dirname` in vite.config.js for resolving input paths in multi-page apps, it always refers to the folder of the vite.config.js file. If specifying a different root, add it to the arguments for `resolve`.
Library mode configuration
Library mode is configured via the `build.lib` config option. It uses a Rollup preset oriented towards shipping libraries. For single entry, it produces `es` and `umd` formats; for multiple entries, it produces `es` and `cjs` formats. Formats can be configured with `build.lib.formats`.
Library mode entry configuration
In library mode, `build.lib` requires an `entry` property (single file path or object mapping names to paths), a `name` property for the global variable name, and a `fileName` property for the output filename (proper extensions are added automatically).
Externalizing dependencies in library mode
In library mode, externalize dependencies that should not be bundled into the library using `rolldownOptions.external`. Provide global variables for externalized deps in `rolldownOptions.output.globals` to use in UMD builds.