Config
- Build Options
- Dep Optimization Options
- Configuring Vite
- Preview Options
- Server Options
- Shared Options
- SSR Options
- Worker Options
Build Options
Unless noted, the options in this section are only applied to build.
build.target
- Type:
string | string[] - Default:
'baseline-widely-available' - Related: Browser Compatibility
Browser compatibility target for the final bundle. The default value is a Vite special value, 'baseline-widely-available', which targets the minimum browser versions compatible with Baseline Widely Available as of a date fixed for each major release (2026-01-01 for this major). Specifically, it is ['chrome111', 'edge111', 'firefox114', 'safari16.4', 'ios16.4'].
Another special value is 'esnext' - which assumes native dynamic imports support and will only perform minimal transpiling.
The transform is performed with Oxc Transformer and the value should be a valid Oxc Transformer target option. Custom targets can either be an ES version (e.g. es2015), a browser with version (e.g. chrome58), or an array of multiple target strings.
Note the build will output a warning if the code contains features that cannot be safely transpiled by Oxc. See Oxc docs for more details.
build.modulePreload
- Type:
boolean | { polyfill?: boolean, resolveDependencies?: ResolveModulePreloadDependenciesFn } - Default:
{ polyfill: true }
By default, a module preload polyfill is automatically injected. The polyfill is auto injected into the proxy module of each index.html entry. If the build is configured to use a non-HTML custom entry via build.rolldownOptions.input, then it is necessary to manually import the polyfill in your custom entry:
import 'vite/modulepreload-polyfill'
Note: the polyfill does not apply to Library Mode. If you need to support browsers without native dynamic import, you should probably avoid using it in your library.
The polyfill can be disabled using { polyfill: false }.
The list of chunks to preload for each dynamic import is computed by Vite. By default, an absolute path including the base will be used when loading these dependencies. If the base is relative ('' or './'), import.meta.url is used at runtime to avoid absolute paths that depend on the final deployed base.
There is experimental support for fine grained control over the dependencies list and their paths using the resolveDependencies function. Give Feedback. It expects a function of type ResolveModulePreloadDependenciesFn:
type ResolveModulePreloadDependenciesFn = (
url: string,
deps: string[],
context: {
hostId: string
hostType: 'html' | 'js'
},
) => string[]
The resolveDependencies function will be called for each dynamic import with a list of the chunks it depends on, and it will also be called for each chunk imported in entry HTML files. A new dependencies array can be returned with these filtered or more dependencies injected, and their paths modified. The deps paths are relative to the build.outDir. The return value should be a relative path to the build.outDir.
/** @type {import('vite').UserConfig} */
const config = {
// prettier-ignore
build: {
// ---cut-before---
modulePreload: {
resolveDependencies: (filename, deps, { hostId, hostType }) => {
return deps.filter(condition)
},
},
// ---cut-after---
},
}
The resolved dependency paths can be further modified using experimental.renderBuiltUrl.
build.polyfillModulePreload
- Type:
boolean - Default:
true - Deprecated use
build.modulePreload.polyfillinstead
Whether to automatically inject a module preload polyfill.
build.outDir
- Type:
string - Default:
dist
Specify the output directory (relative to project root).
build.assetsDir
- Type:
string - Default:
assets
Specify the directory to nest generated assets under (relative to build.outDir). This is not used in Library Mode.
build.assetsInlineLimit
- Type:
number|((filePath: string, content: Buffer) => boolean | undefined) - Default:
4096(4 KiB)
Imported or referenced assets that are smaller than this threshold will be inlined as base64 URLs to avoid extra http requests. Set to 0 to disable inlining altogether.
If a callback is passed, a boolean can be returned to opt-in or opt-out. If nothing is returned the default logic applies.
Git LFS placeholders are automatically excluded from inlining because they do not contain the content of the file they represent.
::: tip Note
If you specify build.lib, build.assetsInlineLimit will be ignored and assets will always be inlined, regardless of file size or being a Git LFS placeholder.
:::
build.cssCodeSplit
- Type:
boolean - Default:
true
Enable/disable CSS code splitting. When enabled, CSS imported in async JS chunks will be preserved as chunks and fetched together when the chunk is fetched.
If disabled, all CSS in the entire project will be extracted into a single CSS file.
::: tip Note
If you specify build.lib, build.cssCodeSplit will be false as default.
:::
build.cssTarget
- Type:
string | string[] - Default: the same as
build.target
This option allows users to set a different browser target for CSS minification from the one used for JavaScript transpilation.
When build.cssMinify is 'lightningcss' (the default), this option takes precedence over css.lightningcss.targets for the minification step.
It should only be used when you are targeting a non-mainstream browser.
One example is Android WeChat WebView, which supports most modern JavaScript features but not the #RGBA hexadecimal color notation in CSS.
In this case, you need to set build.cssTarget to chrome61 to prevent Vite from transforming rgba() colors into #RGBA hexadecimal notations.
build.cssMinify
- Type:
boolean | 'lightningcss' | 'esbuild' - Default:
'lightningcss', butfalseifbuild.minifyis disabled for client build
This option allows users to override CSS minification specifically instead of defaulting to build.minify, so you can configure minification for JS and CSS separately. Vite uses Lightning CSS by default to minify CSS. It can be configured using css.lightningcss. Set the option to 'esbuild' to use esbuild instead.
esbuild must be installed when it is set to 'esbuild'.
npm add -D esbuild
build.sourcemap
- Type:
boolean | 'inline' | 'hidden' - Default:
false
Generate production source maps. If true, a separate sourcemap file will be created. If 'inline', the sourcemap will be appended to the resulting output file as a data URI. 'hidden' works like true except that the corresponding sourcemap comments in the bundled files are suppressed.
build.chunkImportMap
- Type:
boolean - Default:
false - Experimental
- Related: Chunk Import Map Optimization
Whether to use import maps feature to optimize chunk caching efficiency.
Note that this option requires import.meta.resolve support. If you need to support older browsers, check out @vitejs/plugin-legacy.
build.rolldownOptions
- Type:
RolldownOptions
Directly customize the underlying Rolldown bundle. This is the same as options that can be exported from a Rolldown config file and will be merged with Vite's internal Rolldown options. See Rolldown options docs for more details.
Vite overrides Rolldown's default for preserveEntrySignatures. When this option is not set, Vite uses false for regular client builds, 'strict' for library builds, and 'allow-extension' for SSR builds.
Instead of build.rolldownOptions.input, it is recommended to set the top-level input option, because it will be used in dev as well. If build.rolldownOptions.input is set, it overrides the top-level input option for build only.
build.rollupOptions
- Type:
RolldownOptions - Deprecated
This option is an alias of build.rolldownOptions option. Use build.rolldownOptions option instead.
build.dynamicImportVarsOptions
- Type:
{ include?: string | RegExp | (string | RegExp)[], exclude?: string | RegExp | (string | RegExp)[] } - Related: Dynamic Import
Whether to transform dynamic imports with variables.
build.lib
- Type:
{ entry?: string | string[] | { [entryAlias: string]: string }, name?: string, formats?: ('es' | 'cjs' | 'umd' | 'iife')[], fileName?: string | ((format: ModuleFormat, entryName: string) => string), cssFileName?: string } - Related: Library Mode
Build as a library. entry defaults to the top-level input option, and one of them is required since the library cannot use HTML as entry. name is the exposed global variable and is required when formats includes 'umd' or 'iife'. Default formats are ['es', 'umd'], or ['es', 'cjs'], if multiple entries are used.
fileName is the name of the package file output, which defaults to the "name" in package.json. It can also be defined as a function taking the format and entryName as arguments, and returning the file name.
If your package imports CSS, cssFileName can be used to specify the name of the CSS file output. It defaults to the same value as fileName if it's set a string, otherwise it also falls back to the "name" in package.json.
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: ['src/main.js'],
fileName: (format, entryName) => `my-lib-${entryName}.${format}.js`,
cssFileName: 'my-lib-style',
},
},
})
build.license
- Type:
boolean | { fileName?: string } - Default:
false - Related: License
When set to true, the build will generate a .vite/license.md file that includes all bundled dependencies' licenses.
If fileName is passed, it will be used as the license file name relative to the outDir. If it ends with .json, the raw JSON metadata will be generated instead and can be used for further processing. For example:
[
{
"name": "dep-1",
"version": "1.2.3",
"identifier": "CC0-1.0",
"text": "CC0 1.0 Universal\n\n..."
},
{
"name": "dep-2",
"version": "4.5.6",
"identifier": "MIT",
"text": "MIT License\n\n..."
}
]
::: tip
If you'd like to reference the license file in the built code, you can use build.rolldownOptions.output.postBanner to inject a comment at the top of the files. For example:
import { defineConfig } from 'vite'
export default defineConfig({
build: {
license: true,
rolldownOptions: {
output: {
postBanner:
'/* See licenses of bundled dependencies at https://example.com/license.md */',
},
},
},
})
:::
build.manifest
- Type:
boolean | string - Default:
false - Related: Backend Integration
Whether to generate a manifest file that contains a mapping of non-hashed asset filenames to their hashed versions, which can then be used by a server framework to render the correct asset links.
When the value is a string, it will be used as the manifest file path relative to build.outDir. When set to true, the path would be .vite/manifest.json.
If you are writing a plugin and need to inspect each output chunk or asset's related CSS and static assets during the build, you can also use viteMetadata output bundle metadata API.
build.ssrManifest
- Type:
boolean | string - Default:
false - Related: Server-Side Rendering
Whether to generate a SSR manifest file for determining style links and asset preload directives in production.
When the value is a string, it will be used as the manifest file path relative to build.outDir. When set to true, the path would be .vite/ssr-manifest.json.
build.ssr
- Type:
boolean | string - Default:
false - Related: Server-Side Rendering
Produce SSR-oriented build. The value can be a string to directly specify the SSR entry, or true, which requires specifying the SSR entry via input or build.rolldownOptions.input.
build.emitAssets
- Type:
boolean - Default:
false
During non-client builds, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in other environments build. It is responsibility of the framework to merge the assets with a post build step.
build.ssrEmitAssets
- Type:
boolean - Default:
false
During the SSR build, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in both the client and SSR build. It is responsibility of the framework to merge the assets with a post build step. This option will be replaced by build.emitAssets once Environment API is stable.
build.minify
- Type:
boolean | 'oxc' | 'terser' | 'esbuild' - Default:
'oxc'for client build,falsefor SSR build
Set to false to disable minification, or specify the minifier to use. The default is Oxc Minifier which is 30 ~ 90x faster than terser and only 0.5 ~ 2% worse compression. Benchmarks
build.minify: 'esbuild' is deprecated and will be removed in the future.
Note the build.minify option does not minify whitespaces when using the 'es' format in lib mode, as it removes pure annotations and breaks tree-shaking.
esbuild or Terser must be installed when it is set to 'esbuild' or 'terser' respectively.
npm add -D esbuild
npm add -D terser
build.terserOptions
- Type:
TerserOptions
Additional minify options to pass on to Terser.
In addition, you can also pass a maxWorkers: number option to specify the max number of workers to spawn. Defaults to the number of CPUs minus 1.
build.write
- Type:
boolean - Default:
true
Set to false to disable writing the bundle to disk. This is mostly used in programmatic build() calls where further post processing of the bundle is needed before writing to disk.
build.emptyOutDir
- Type:
boolean - Default:
trueifoutDiris insideroot
By default, Vite will empty the outDir on build if it is inside project root. It will emit a warning if outDir is outside of root to avoid accidentally removing important files. You can explicitly set this option to suppress the warning. This is also available via command line as --emptyOutDir.
build.copyPublicDir
- Type:
boolean - Default:
true
By default, Vite will copy files from the publicDir into the outDir on build. Set to false to disable this.
build.reportCompressedSize
- Type:
boolean - Default:
true
Enable/disable gzip-compressed size reporting. Compressing large output files can be slow, so disabling this may increase build performance for large projects.
build.chunkSizeWarningLimit
- Type:
number - Default:
500
Limit for chunk size warnings (in kB). It is compared against the uncompressed chunk size as the JavaScript size itself is related to the execution time.
build.watch
- Type:
WatcherOptions| null - Default:
null
Set to {} to enable Rolldown watcher. This is mostly used in cases that involve build-only plugins or integrations processes.
::: warning Using Vite on Windows Subsystem for Linux (WSL) 2
There are cases that file system watching does not work with WSL2.
See server.watch for more details.
:::
Dep Optimization Options
Unless noted, the options in this section are only applied to the dependency optimizer, which is only used in dev.
optimizeDeps.entries
- Type:
string | string[]
By default, Vite will crawl all your .html files to detect dependencies that need to be pre-bundled (ignoring node_modules, build.outDir, __tests__ and coverage). If the top-level input or build.rolldownOptions.input is specified, Vite will crawl those entry points instead.
If neither of these fit your needs, you can specify custom entries using this option - the value should be a tinyglobby pattern or array of patterns that are relative from Vite project root. This will overwrite default entries inference. Only node_modules and build.outDir folders will be ignored by default when optimizeDeps.entries is explicitly defined. If other folders need to be ignored, you can use an ignore pattern as part of the entries list, marked with an initial !. node_modules will not be ignored for patterns that explicitly include the string node_modules.
optimizeDeps.exclude
- Type:
string[]
Dependencies to exclude from pre-bundling.
:::warning CommonJS
CommonJS dependencies should not be excluded from optimization. If an ESM dependency is excluded from optimization, but has a nested CommonJS dependency, the CommonJS dependency should be added to optimizeDeps.include. Example:
import { defineConfig } from 'vite'
// ---cut---
export default defineConfig({
optimizeDeps: {
include: ['esm-dep > cjs-dep'],
},
})
:::
optimizeDeps.include
- Type:
string[]
By default, linked packages not inside node_modules are not pre-bundled. Use this option to force a linked package to be pre-bundled.
Experimental: If you're using a library with many deep imports, you can also specify a trailing glob pattern to pre-bundle all deep imports at once. This will avoid constantly pre-bundling whenever a new deep import is used. Give Feedback. For example:
import { defineConfig } from 'vite'
// ---cut---
export default defineConfig({
optimizeDeps: {
include: ['my-lib/components/**/*.vue'],
},
})
optimizeDeps.rolldownOptions
- Type:
Omit<RolldownOptions, 'input' | 'logLevel' | 'output'> & { output?: Omit<RolldownOutputOptions, 'format' | 'sourcemap' | 'dir' | 'banner'> }
Options to pass to Rolldown during the dep scanning and optimization.
Certain options are omitted since changing them would not be compatible with Vite's dep optimization.
pluginsare merged with Vite's dep plugin
optimizeDeps.esbuildOptions
- Type:
Omit<EsbuildBuildOptions, 'bundle' | 'entryPoints' | 'external' | 'write' | 'watch' | 'outdir' | 'outfile' | 'outbase' | 'outExtension' | 'metafile'> - Deprecated
This option is converted to optimizeDeps.rolldownOptions internally. Use optimizeDeps.rolldownOptions instead.
optimizeDeps.force
- Type:
boolean
Set to true to force dependency pre-bundling, ignoring previously cached optimized dependencies.
optimizeDeps.noDiscovery
- Type:
boolean - Default:
false
When set to true, automatic dependency discovery will be disabled and only dependencies listed in optimizeDeps.include will be optimized. CJS-only dependencies must be present in optimizeDeps.include during dev.
optimizeDeps.holdUntilCrawlEnd
- Experimental: Give Feedback
- Type:
boolean - Default:
true
When enabled, it will hold the first optimized deps results until all static imports are crawled on cold start. This avoids the need for full-page reloads when new dependencies are discovered and they trigger the generation of new common chunks. If all dependencies are found by the scanner plus the explicitly defined ones in include, it is better to disable this option to let the browser process more requests in parallel.
optimizeDeps.disabled
- Deprecated
- Experimental: Give Feedback
- Type:
boolean | 'build' | 'dev' - Default:
'build'
This option is deprecated. As of Vite 5.1, pre-bundling of dependencies during build have been removed. Setting optimizeDeps.disabled to true or 'dev' disables the optimizer, and configured to false or 'build' leaves the optimizer during dev enabled.
To disable the optimizer completely, use optimizeDeps.noDiscovery: true to disallow automatic discovery of dependencies and leave optimizeDeps.include undefined or empty.
:::warning
Optimizing dependencies during build time was an experimental feature. Projects trying out this strategy also removed @rollup/plugin-commonjs using build.commonjsOptions: { include: [] }. If you did so, a warning will guide you to re-enable it to support CJS only packages while bundling.
:::
optimizeDeps.needsInterop
- Experimental
- Type:
string[]
Forces ESM interop when importing these dependencies. Vite is able to properly detect when a dependency needs interop, so this option isn't generally needed. However, different combinations of dependencies could cause some of them to be prebundled differently. Adding these packages to needsInterop can speed up cold start by avoiding full-page reloads. You'll receive a warning if this is the case for one of your dependencies, suggesting to add the package name to this array in your config.
Configuring Vite
When running vite from the command line, Vite will automatically try to resolve a config file named vite.config.js inside project root (other JS and TS extensions are also supported).
The most basic config file looks like this:
export default {
// config options
}
Note that to use ES modules syntax in the config file, it should be in a file detected as ESM by Node.js, e.g. .mjs or .js with "type": "module" in closest package.json.
You can also explicitly specify a config file to use with the --config CLI option (resolved relative to cwd):
vite --config my-config.js
Watch an interactive lesson on Scrimba
::: tip CONFIG LOADING
By default, Vite uses Rolldown to bundle the config into a temporary file and load it. If you're using an environment that supports TypeScript (e.g. Node 22.18+), or if you're only writing plain JavaScript, you can specify --configLoader native to use the environment's native runtime to load the config file. configLoader: 'native' is planned to become the default in a future major version.
:::
Config Intellisense
Since Vite ships with TypeScript typings, you can leverage your IDE's intellisense with JSDoc type hints:
/** @type {import('vite').UserConfig} */
export default {
// ...
}
Alternatively, you can use the defineConfig helper which should provide intellisense without the need for JSDoc annotations:
import { defineConfig } from 'vite'
export default defineConfig({
// ...
})
Vite also supports TypeScript config files. You can use vite.config.ts with the defineConfig helper function above, or with the satisfies operator:
import type { UserConfig } from 'vite'
export default {
// ...
} satisfies UserConfig
Conditional Config
If the config needs to conditionally determine options based on the command (serve or build), the mode being used, if it's an SSR build (isSsrBuild), or is previewing the build (isPreview), it can export a function instead:
import { defineConfig } from 'vite'
// ---cut---
export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
if (command === 'serve') {
return {
// dev specific config
}
} else {
// command === 'build'
return {
// build specific config
}
}
})
It is important to note that in Vite's API the command value is serve during dev (in the cli vite, vite dev, and vite serve are aliases), and build when building for production (vite build).
isSsrBuild and isPreview are additional optional flags to differentiate the kind of build and serve commands respectively. Some tools that load the Vite config may not support these flags and will pass undefined instead. Hence, it's recommended to use explicit comparison against true and false.
Async Config
If the config needs to call async functions, it can export an async function instead. And this async function can also be passed through defineConfig for improved intellisense support:
import { defineConfig } from 'vite'
// ---cut---
export default defineConfig(async ({ command, mode }) => {
const data = await asyncFunction()
return {
// vite config
}
})
Using Environment Variables in Config
Environment variables available while the config itself is being evaluated are only those that already exist in the current process environment (process.env). Vite deliberately defers loading any .env* files until after the user config has been resolved because the set of files to load depends on config options like root and envDir, and also on the final mode.
This means: variables defined in .env, .env.local, .env.[mode], or .env.[mode].local are not automatically injected into process.env while your vite.config.* is running. They are automatically loaded later and exposed to application code via import.meta.env (with the default VITE_ prefix filter) exactly as documented in Env Variables and Modes. So if you only need to pass values from .env* files to the app, you don't need to call anything in the config.
If, however, values from .env* files must influence the config itself (for example to set server.port, conditionally enable plugins, or compute define replacements), you can load them manually using the exported loadEnv helper.
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
// Load env file based on `mode` in the current working directory.
// Set the third parameter to '' to load all env regardless of the
// `VITE_` prefix.
const env = loadEnv(mode, process.cwd(), '')
return {
define: {
// Provide an explicit app-level constant derived from an env var.
__APP_ENV__: JSON.stringify(env.APP_ENV),
},
// Example: use an env var to set the dev server port conditionally.
server: {
port: env.APP_PORT ? Number(env.APP_PORT) : 5173,
},
}
})
Debugging the Config File in VS Code
For the most reliable debugging experience, use the native config loader when starting Vite:
vite --configLoader native
The native loader executes the original config file directly, so breakpoints in the config file and in plugin hooks such as transform map to the original source. It requires a runtime that supports the syntax used by your config file, such as Node.js 22.18+ for TypeScript files.
When using --configLoader bundle (the current default, though native is planned to become the default in a future major version), Vite generates an inline source map and writes the bundled config to node_modules/.vite-temp before loading it. If you need to use the bundle loader, add the temporary directory for the JavaScript Debug Terminal in .vscode/settings.json:
{
"debug.javascript.terminalOptions": {
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**",
"**/node_modules/.vite-temp/**"
]
}
}
This setting only applies to the JavaScript Debug Terminal, it does not affect launch configurations started from the Run and Debug view. To support this for the Run and Debug view, add the temporary directory in .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Vite",
"runtimeExecutable": "npm",
"runtimeArgs": ["exec", "vite", "--configLoader", "bundle"],
"console": "integratedTerminal",
"sourceMaps": true,
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**",
"**/node_modules/.vite-temp/**"
]
}
]
}
Preview Options
Unless noted, the options in this section are only applied to preview.
preview.host
- Type:
string | boolean - Default:
server.host
Specify which IP addresses the server should listen on.
Set this to 0.0.0.0 or true to listen on all addresses, including LAN and public addresses.
This can be set via the CLI using --host 0.0.0.0 or --host.
::: tip NOTE
There are cases when other servers might respond instead of Vite.
See server.host for more details.
:::
preview.allowedHosts
- Type:
string[] | true - Default:
server.allowedHosts
The hostnames that Vite is allowed to respond to.
See server.allowedHosts for more details.
preview.port
- Type:
number - Default:
4173
Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on.
Example:
export default defineConfig({
server: {
port: 3030,
},
preview: {
port: 8080,
},
})
preview.strictPort
- Type:
boolean - Default:
server.strictPort
Set to true to exit if port is already in use, instead of automatically trying the next available port.
preview.https
- Type:
https.ServerOptions - Default:
server.https
Enable TLS + HTTP/2.
See server.https for more details.
preview.open
- Type:
boolean | string - Default:
server.open
Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname. If you want to open the server in a specific browser you like, you can set the env process.env.BROWSER (e.g. firefox). You can also set process.env.BROWSER_ARGS to pass additional arguments (e.g. --incognito).
BROWSER and BROWSER_ARGS are also special environment variables you can set in the .env file to configure it. See the open package for more details.
preview.proxy
- Type:
Record<string, string | ProxyOptions> - Default:
server.proxy
Configure custom proxy rules for the preview server. Expects an object of { key: options } pairs. If the key starts with ^, it will be interpreted as a RegExp. The configure option can be used to access the proxy instance.
Uses http-proxy-3. Full options here.
preview.cors
- Type:
boolean | CorsOptions - Default:
server.cors
Configure CORS for the preview server.
See server.cors for more details.
preview.headers
- Type:
OutgoingHttpHeaders
Specify server response headers.
Server Options
Unless noted, the options in this section are only applied to dev.
server.host
- Type:
string | boolean - Default:
'localhost'
Specify which IP addresses the server should listen on.
Set this to 0.0.0.0 or true to listen on all addresses, including LAN and public addresses.
This can be set via the CLI using --host 0.0.0.0 or --host.
::: tip NOTE
There are cases when other servers might respond instead of Vite.
The first case is when localhost is used. Node.js's dns.setDefaultResultOrder changes how DNS-resolved addresses are ordered, and browsers may use a different resolved address than the one Vite is listening to. Vite prints the resolved address when it differs.
The second case is when wildcard hosts (e.g. 0.0.0.0) are used. This is because servers listening on non-wildcard hosts take priority over those listening on wildcard hosts.
:::
::: tip Accessing the server on WSL2 from your LAN
When running Vite on WSL2, it is not sufficient to set host: true to access the server from your LAN.
See the WSL document for more details.
:::
server.allowedHosts
- Type:
string[] | true - Default:
[]
The hostnames that Vite is allowed to respond to.
localhost and domains under .localhost and all IP addresses are allowed by default.
When using HTTPS, this check is skipped.
If a string starts with ., it will allow that hostname without the . and all subdomains under the hostname. For example, .example.com will allow example.com, foo.example.com, and foo.bar.example.com. If set to true, the server is allowed to respond to requests for any hosts.
::: details What hosts are safe to be added?
Hosts that you have control over which IP addresses they resolve to are safe to add to the list of allowed hosts.
For example, if you own a domain vite.dev, you can add vite.dev and .vite.dev to the list. If you don't own that domain and you cannot trust the owner of that domain, you should not add it.
Especially, you should never add Top-Level Domains like .com to the list. This is because anyone can purchase a domain like example.com and control the IP address it resolves to.
:::
::: danger
Setting server.allowedHosts to true allows any website to send requests to your dev server through DNS rebinding attacks, allowing them to download your source code and content. We recommend always using an explicit list of allowed hosts. See GHSA-vg6x-rcgg-rjx6 for more details.
:::
::: details Configure via environment variable
You can set the environment variable __VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS to add additional allowed hosts. Use commas to separate multiple hosts (e.g., host1.example.com,host2.example.com).
:::
server.port
- Type:
number - Default:
5173
Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on.
server.strictPort
- Type:
boolean
Set to true to exit if port is already in use, instead of automatically trying the next available port.
server.https
- Type:
https.ServerOptions
Enable TLS + HTTP/2. The value is an options object passed to https.createServer().
A valid certificate is needed. For a basic setup, you can add @vitejs/plugin-basic-ssl to the project plugins, which will automatically create and cache a self-signed certificate. But we recommend creating your own certificates.
server.open
- Type:
boolean | string
Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname. If you want to open the server in a specific browser you like, you can set the env process.env.BROWSER (e.g. firefox). You can also set process.env.BROWSER_ARGS to pass additional arguments (e.g. --incognito).
BROWSER and BROWSER_ARGS are also special environment variables you can set in the .env file to configure it. See the open package for more details.
Example:
export default defineConfig({
server: {
open: '/docs/index.html',
},
})
server.proxy
- Type:
Record<string, string | ProxyOptions>
Configure custom proxy rules for the dev server. Expects an object of { key: options } pairs. Any requests whose request path starts with that key will be proxied to the specified target. If the key starts with ^, it will be interpreted as a RegExp. The configure option can be used to access the proxy instance. If a request matches any of the configured proxy rules, the request won't be transformed by Vite.
Note that if you are using non-relative base, you must prefix each key with that base.
Extends http-proxy-3. Additional options are here.
In some cases, you might also want to configure the underlying dev server (e.g. to add custom middlewares to the internal connect app). In order to do that, you need to write your own plugin and use configureServer function.
Example:
export default defineConfig({
server: {
proxy: {
// string shorthand:
// http://localhost:5173/foo
// -> http://localhost:4567/foo
'/foo': 'http://localhost:4567',
// with options:
// http://localhost:5173/api/bar
// -> http://jsonplaceholder.typicode.com/bar
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
// with RegExp:
// http://localhost:5173/fallback/
// -> http://jsonplaceholder.typicode.com/
'^/fallback/.*': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/fallback/, ''),
},
// Using the proxy instance
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
configure: (proxy, options) => {
// proxy will be an instance of 'http-proxy-3'
},
},
// Proxying websockets or socket.io:
// ws://localhost:5173/socket.io
// -> ws://localhost:5174/socket.io
// Exercise caution using `rewriteWsOrigin` as it can leave the
// proxying open to CSRF attacks.
'/socket.io': {
target: 'ws://localhost:5174',
ws: true,
rewriteWsOrigin: true,
},
},
},
})
::: warning Origin check for WebSockets
Vite does not check the origin of WebSocket requests before proxying. The proxy target is expected to check the Origin header or other checks. Note that the rewriteWsOrigin option will rewrite the origin to the target origin and will cause the origin check to be bypassed.
:::
server.cors
- Type:
boolean | CorsOptions - Default:
{ origin: /^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/ }(allows localhost,127.0.0.1and::1)
Configure CORS for the dev server. Pass an options object to fine tune the behavior or true to allow any origin.
::: danger
Setting server.cors to true allows any website to send requests to your dev server and download your source code and content. We recommend always using an explicit list of allowed origins.
:::
server.headers
- Type:
OutgoingHttpHeaders
Specify server response headers.
server.hmr
- Type:
boolean | { overlay?: boolean }
Disable or configure HMR behavior.
Set server.hmr.overlay to false to disable the server error overlay.
::: warning Deprecated Options
The WebSocket-related options (protocol, host, port, path, clientPort, timeout, server) are deprecated. Use server.ws instead. These options are automatically synced, so existing configurations will continue to work.
:::
server.ws
- Type:
false | { protocol?: string, host?: string, port?: number, path?: string, timeout?: number, clientPort?: number, server?: Server }
Configure WebSocket connection options. Set to false to disable the WebSocket connection entirely.
protocol- WebSocket protocol (wsorwss)host- WebSocket server hostport- WebSocket server portpath- WebSocket pathclientPort- Override the port on the client side, allowing you to serve the websocket on a different port than the client code looks for it ontimeout- Connection timeout in milliseconds (default: 30000)server- Use a custom HTTP server for WebSocket connections
When server.ws.server is defined, Vite will process the WebSocket connection requests through the provided server. If not in middleware mode, Vite will attempt to process WebSocket connection requests through the existing server. This can be helpful when using self-signed certificates or when you want to expose Vite over a network on a single port.
export default defineConfig({
server: {
ws: {
protocol: 'wss',
host: 'localhost',
port: 3001,
},
},
})
Check out vite-setup-catalogue for some examples.
::: tip NOTE
With the default configuration, reverse proxies in front of Vite are expected to support proxying WebSocket. If the Vite HMR client fails to connect WebSocket, the client will fall back to connecting the WebSocket directly to the Vite HMR server bypassing the reverse proxies:
Direct websocket connection fallback. Check out https://vite.dev/config/server-options.html#server-ws to remove the previous connection error.
The error that appears in the Browser when the fallback happens can be ignored. To avoid the error by directly bypassing reverse proxies, you could either:
- configure the reverse proxy to proxy WebSocket too
- set
server.strictPort = trueand setserver.ws.clientPortto the same value withserver.port - set
server.ws.portto a different value fromserver.port
:::
server.forwardConsole
- Type:
boolean | { unhandledErrors?: boolean, logLevels?: ('error' | 'warn' | 'info' | 'log' | 'debug')[] } - Default: auto (
truewhen an AI coding agent is detected based onstd-env, otherwisefalse)
Forward browser runtime events to the Vite server console during development.
trueenables forwarding unhandled errors andconsole.error/console.warnlogs.unhandledErrorscontrols forwarding uncaught exceptions and unhandled promise rejections.logLevelscontrols whichconsole.*calls are forwarded.
For example:
export default defineConfig({
server: {
forwardConsole: {
unhandledErrors: true,
logLevels: ['warn', 'error'],
},
},
})
When unhandled errors are forwarded, they are logged in the server terminal with enhanced formatting, for example:
1:18:38 AM [vite] (client) [Unhandled error] Error: this is test error
> testError src/main.ts:20:8
18|
19| function testError() {
20| throw new Error('this is test error')
| ^
21| }
22|
> HTMLButtonElement.<anonymous> src/main.ts:6:2
server.warmup
- Type:
{ clientFiles?: string[], ssrFiles?: string[] } - Related: Warm Up Frequently Used Files
Warm up files to transform and cache the results in advance. This improves the initial page load during server starts and prevents transform waterfalls.
clientFiles are files that are used in the client only, while ssrFiles are files that are used in SSR only. They accept an array of file paths or tinyglobby patterns relative to the root.
Make sure to only add files that are frequently used to not overload the Vite dev server on startup.
export default defineConfig({
server: {
warmup: {
clientFiles: ['./src/components/*.vue', './src/utils/big-utils.js'],
ssrFiles: ['./src/server/modules/*.js'],
},
},
})
server.watch
- Type:
object | null
File system watcher options to pass on to chokidar.
When bundled-dev mode is enabled, Rolldown watch options (for example, usePolling, pollInterval, useDebounce, debounceDuration, include, exclude) are also accepted. The chokidar-only options are still used by the chokidar watcher, which keeps watching files outside the module graph, such as config file dependencies and env files.
The Vite server watcher watches the root and skips the .git/, node_modules/, test-results/, and Vite's cacheDir and build.outDir directories by default. When updating a watched file, Vite will apply HMR and update the page only if needed.
If set to null, no files will be watched. server.watcher will provide a compatible event emitter, but calling add or unwatch will have no effect.
::: warning Watching files in node_modules
It's currently not possible to watch files and packages in node_modules. For further progress and workarounds, you can follow issue #8619.
:::
::: warning Using Vite on Windows Subsystem for Linux (WSL) 2
When running Vite on WSL2, file system watching does not work when a file is edited by Windows applications (non-WSL2 process). This is due to a WSL2 limitation. This also applies to running on Docker with a WSL2 backend.
To fix it, you could either:
- Recommended: Use WSL2 applications to edit your files.
- It is also recommended to move the project folder outside of a Windows filesystem. Accessing Windows filesystem from WSL2 is slow. Removing that overhead will improve performance.
- Set
{ usePolling: true }.- Note that
usePollingleads to high CPU utilization.
- Note that
:::
server.middlewareMode
- Type:
boolean | { server: http.Server } - Default:
false
Create Vite server in middleware mode.
If proxy is setup for WebSocket, the server should be provided to bind the proxy correctly.
import express from 'express'
import { createServer as createViteServer } from 'vite'
async function createServer() {
const app = express()
// Create Vite server in middleware mode
const vite = await createViteServer({
server: { middlewareMode: true },
// don't include Vite's default HTML handling middlewares
appType: 'custom',
})
// Use vite's connect instance as middleware
app.use(vite.middlewares)
app.use('*', async (req, res) => {
// Since `appType` is `'custom'`, should serve response here.
// Note: if `appType` is `'spa'` or `'mpa'`, Vite includes middlewares
// to handle HTML requests and 404s so user middlewares should be added
// before Vite's middlewares to take effect instead
})
}
createServer()
server.fs.strict
- Type:
boolean - Default:
true(enabled by default since Vite 2.7)
Restrict serving files outside of workspace root.
server.fs.allow
- Type:
string[]
Restrict files that could be served via /@fs/. When server.fs.strict is set to true, accessing files outside this directory list that aren't imported from an allowed file will result in a 403.
Both directories and files can be provided.
Vite will search for the root of the potential workspace and use it as default. A valid workspace met the following conditions, otherwise will fall back to the project root.
- contains
workspacesfield inpackage.json - contains one of the following file
lerna.jsonpnpm-workspace.yaml
Accepts a path to specify the custom workspace root. Could be a absolute path or a path relative to project root. For example:
export default defineConfig({
server: {
fs: {
// Allow serving files from one level up to the project root
allow: ['..'],
},
},
})
When server.fs.allow is specified, the auto workspace root detection will be disabled. To extend the original behavior, a utility searchForWorkspaceRoot is exposed:
import { defineConfig, searchForWorkspaceRoot } from 'vite'
export default defineConfig({
server: {
fs: {
allow: [
// search up for workspace root
searchForWorkspaceRoot(process.cwd()),
// your custom rules
'/path/to/custom/allow_directory',
'/path/to/custom/allow_file.demo',
],
},
},
})
server.fs.deny
- Type:
string[] - Default:
['.env', '.env.*', '*.{crt,pem,key,p12,pfx,cer,der}', '.npmrc', '.yarnrc.yml', '**/.git/**']
Blocklist for sensitive files being restricted to be served by Vite dev server. This will have higher priority than server.fs.allow. picomatch patterns are supported.
::: tip NOTE
This blocklist does not apply to the public directory. All files in the public directory are served without any filtering, since they are copied directly to the output directory during build.
:::
::: tip NOTE
The deny filter is applied against the module id and the id with query parameters stripped. Since a plugin can read files from any files in its load hook (including resolving symlinks to denied paths), Vite cannot guarantee that a denied file is inaccessible through an alternative path. If you have an alternative path, include it in the deny list as well.
:::
server.origin
- Type:
string
Defines the origin of the generated asset URLs during development.
export default defineConfig({
server: {
origin: 'http://127.0.0.1:8080',
},
})
server.sourcemapIgnoreList
- Type:
false | (sourcePath: string, sourcemapPath: string) => boolean - Default:
(sourcePath) => /(?:^|[\\/])node_modules(?:[\\/]|$)/.test(sourcePath)
Whether or not to ignore source files in the server sourcemap, used to populate the x_google_ignoreList source map extension.
server.sourcemapIgnoreList is the equivalent of build.rolldownOptions.output.sourcemapIgnoreList for the dev server. A difference between the two config options is that the Rolldown function is called with a relative path for sourcePath while server.sourcemapIgnoreList is called with an absolute path. During dev, most modules have the map and the source in the same folder, so the relative path for sourcePath is the file name itself. In these cases, absolute paths make it convenient to be used instead.
By default, it excludes all paths that contain node_modules as a path segment. You can pass false to disable this behavior, or, for full control, a function that takes the source path and sourcemap path and returns whether to ignore the source path.
export default defineConfig({
server: {
// This is the default value, and will add all files that have
// node_modules as a path segment to the ignore list.
sourcemapIgnoreList(sourcePath, sourcemapPath) {
return /(?:^|[\\/])node_modules(?:[\\/]|$)/.test(sourcePath)
},
},
})
::: tip Note
server.sourcemapIgnoreList and build.rolldownOptions.output.sourcemapIgnoreList need to be set independently. server.sourcemapIgnoreList is a server only config and doesn't get its default value from the defined Rolldown options.
:::
Shared Options
Unless noted, the options in this section are applied to all dev, build, and preview.
root
- Type:
string - Default:
process.cwd()
Project root directory (where index.html is located). Can be an absolute path, or a path relative to the current working directory.
See Project Root for more details.
base
- Type:
string - Default:
/ - Related:
server.origin
Base public path when served in development or production. Valid values include:
- Absolute URL pathname, e.g.
/foo/ - Full URL, e.g.
https://bar.com/foo/(The origin part won't be used in development so the value is the same as/foo/) - Empty string or
./(for embedded deployment)
See Public Base Path for more details.
mode
- Type:
string - Default:
'development'for serve,'production'for build
Specifying this in config will override the default mode for both serve and build. This value can also be overridden via the command line --mode option.
See Env Variables and Modes for more details.
input
- Type:
string | string[] | { [entryAlias: string]: string }
Entry points of your application, resolved relative to the project root. This works as the default value for build.rolldownOptions.input, build.lib.entry, build.ssr (if true), and optimizeDeps.entries when those are not set explicitly.
This is useful when your application does not use an index.html entry, so you only need to declare the entry once instead of repeating it across the options above.
import { defineConfig } from 'vite'
export default defineConfig({
input: 'src/main.ts',
})
define
- Type:
Record<string, any>
Define global constant replacements. Entries will be defined as globals during dev and statically replaced during build.
Vite uses Oxc's define feature to perform replacements, so value expressions must be a string that contains a JSON-serializable value (null, boolean, number, string, array, or object) or a single identifier. For non-string values, Vite will automatically convert it to a string with JSON.stringify.
Example:
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify('v1.0.0'),
__API_URL__: 'window.__backend_api_url',
},
})
::: tip NOTE
For TypeScript users, make sure to add the type declarations in the vite-env.d.ts file to get type checks and Intellisense.
Example:
// vite-env.d.ts
declare const __APP_VERSION__: string
:::
plugins
- Type:
(Plugin | Plugin[] | Promise<Plugin | Plugin[]>)[]
Array of plugins to use. Falsy plugins are ignored and arrays of plugins are flattened. If a promise is returned, it would be resolved before running. See Plugin API for more details on Vite plugins.
publicDir
- Type:
string | false - Default:
"public"
Directory to serve as plain static assets. Files in this directory are served at / during dev and copied to the root of outDir during build, and are always served or copied as-is without transform. The value can be either an absolute file system path or a path relative to project root.
Defining publicDir as false disables this feature.
See The public Directory for more details.
cacheDir
- Type:
string - Default:
"node_modules/.vite"
Directory to save cache files. Files in this directory are pre-bundled deps or some other cache files generated by vite, which can improve the performance. You can use --force flag or manually delete the directory to regenerate the cache files. The value can be either an absolute file system path or a path relative to project root. Default to .vite when no package.json is detected.
resolve.alias
- Type:
Record<string, string> | Array<{ find: string | RegExp, replacement: string }>
Defines aliases used to replace values in import or require statements. This works similar to @rollup/plugin-alias.
The order of the entries is important, in that the first defined rules are applied first.
When aliasing to file system paths, always use absolute paths. Relative alias values will be used as-is and will not be resolved into file system paths.
More advanced custom resolution can be achieved through plugins.
::: warning Using with SSR
If you have configured aliases for SSR externalized dependencies, you may want to alias the actual node_modules packages. Both Yarn and pnpm support aliasing via the npm: prefix.
:::
Object Format (Record<string, string>)
The Object format allows specifying aliases as a key, and the corresponding value as the actual import value. For example:
resolve: {
alias: {
utils: '../../../utils',
'batman-1.0.0': './joker-1.5.0'
}
}
Array Format (Array<{ find: string | RegExp, replacement: string }>)
The Array format allows specifying aliases as objects, which can be useful for complex key/value pairs.
resolve: {
alias: [
{ find: 'utils', replacement: '../../../utils' },
{ find: 'batman-1.0.0', replacement: './joker-1.5.0' },
]
}
When find is a regular expression, the replacement can use replacement patterns, such as $1. For example, to remove extensions with another, a pattern like the following might be used:
{ find:/^(.*)\.js$/, replacement: '$1.alias' }
resolve.dedupe
- Type:
string[]
If you have duplicated copies of the same dependency in your app (likely due to hoisting or linked packages in monorepos), use this option to force Vite to always resolve listed dependencies to the same copy (from project root).
:::warning SSR + ESM
For SSR builds, deduplication does not work for ESM build outputs configured from build.rolldownOptions.output. A workaround is to use CJS build outputs until ESM has better plugin support for module loading.
:::
resolve.conditions
- Type:
string[] - Default:
['module', 'browser', 'development|production'](defaultClientConditions)
Additional allowed conditions when resolving Conditional Exports from a package.
A package with conditional exports may have the following exports field in its package.json:
{
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.js"
}
}
}
Here, import and require are "conditions". Conditions can be nested and should be specified from most specific to least specific.
development|production is a special value that is replaced with production or development depending on the value of process.env.NODE_ENV. It is replaced with production when process.env.NODE_ENV === 'production' and development otherwise.
Note that import, require, default conditions are always applied if the requirements are met.
In addition, the style condition is applied when resolving style imports, e.g. @import 'my-library'. For some CSS pre-processors, their corresponding conditions are also applied, i.e. sass for Sass and less for Less.
resolve.mainFields
- Type:
string[] - Default:
['browser', 'module', 'jsnext:main', 'jsnext'](defaultClientMainFields)
List of fields in package.json to try when resolving a package's entry point. Note this takes lower precedence than conditional exports resolved from the exports field: if an entry point is successfully resolved from exports, the main field will be ignored.
resolve.extensions
- Type:
string[] - Default:
['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']
List of file extensions to try for imports that omit extensions. Note it is NOT recommended to omit extensions for custom import types (e.g. .vue) since it can interfere with IDE and type support.
resolve.preserveSymlinks
- Type:
boolean - Default:
false
Enabling this setting causes vite to determine file identity by the original file path (i.e. the path without following symlinks) instead of the real file path (i.e. the path after following symlinks).
resolve.tsconfigPaths
- Type:
boolean - Default:
false
Enables the tsconfig paths resolution feature. paths option in tsconfig.json will be used to resolve imports. See Features for more details.
paths only applies to a file matched by a tsconfig.json through its files or include. Non-JS extension files should be explicitly listed in them, since a bare "src" or "**/*" include only matches TS/JS extensions, aligning with TypeScript's behavior. For example, to use a paths alias inside a CSS file (such as @import '@/foo.css'), list those files in files, or add an explicit extension to include:
{
"include": ["src", "src/**/*.css", "src/**/*.scss"]
}
::: warning Less is not supported
resolve.tsconfigPaths does not apply inside .less files. Less only gives Vite the importing file's directory, not the file itself, so Vite cannot find the tsconfig.json that matches it. Use a relative path or resolve.alias for @import in Less.
:::
html.cspNonce
A nonce value placeholder that will be used when generating script / style tags. Setting this value will also generate a meta tag with nonce value.
html.additionalAssetSources
- Type:
Record<string, HtmlAssetSource>
interface HtmlAssetSource {
srcAttributes?: string[]
srcsetAttributes?: string[]
filter?: (data: {
key: string
value: string
attributes: Record<string, string>
}) => boolean
}
Define additional HTML elements and attributes to be treated as asset sources. This extends the built-in list that includes standard elements like <img src>, <video src>, <link href>, etc.
This is useful when using custom web components or non-standard attributes (like data-*) that reference assets.
Example:
export default defineConfig({
html: {
additionalAssetSources: {
// Custom web component
'html-import': { srcAttributes: ['src'] },
// Add data-* attributes to existing element
img: { srcAttributes: ['data-src-dark', 'data-src-light'] },
// With srcset format
'my-picture': { srcsetAttributes: ['data-srcset'] },
// With filter function
'my-component': {
srcAttributes: ['asset'],
filter: ({ attributes }) => attributes.type === 'image',
},
},
},
})
css.modules
- Type:
interface CSSModulesOptions { getJSON?: ( cssFileName: string, json: Record<string, string>, outputFileName: string, ) => void scopeBehaviour?: 'global' | 'local' globalModulePaths?: RegExp[] exportGlobals?: boolean generateScopedName?: | string | ((name: string, filename: string, css: string) => string) hashPrefix?: string /** * default: undefined */ localsConvention?: | 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly' | (( originalClassName: string, generatedClassName: string, inputFile: string, ) => string) }
Configure CSS modules behavior. The options are passed on to postcss-modules.
This option doesn't have any effect when using Lightning CSS. If enabled, css.lightningcss.cssModules should be used instead.
css.postcss
- Type:
string | (postcss.ProcessOptions & { plugins?: postcss.AcceptedPlugin[] })
Inline PostCSS config or a custom directory to search PostCSS config from (default is project root).
For inline PostCSS config, it expects the same format as postcss.config.js. But for plugins property, only array format can be used.
The search is done using postcss-load-config and only the supported config file names are loaded. Config files outside the workspace root (or the project root if no workspace is found) are not searched by default. You can specify a custom path outside of the root to load the specific config file instead if needed.
Note if an inline config is provided, Vite will not search for other PostCSS config sources.
css.preprocessorOptions
- Type:
Record<string, object>
Specify options to pass to CSS pre-processors. The file extensions are used as keys for the options. The supported options for each preprocessor can be found in their respective documentation:
sass/scss:- Uses
sass-embeddedif installed, otherwise usessass. For the best performance, it's recommended to install thesass-embeddedpackage. - Options
- Uses
less: Options.styl/stylus: Onlydefineis supported, which can be passed as an object.
Example:
export default defineConfig({
css: {
preprocessorOptions: {
less: {
math: 'parens-division',
},
styl: {
define: {
$specialColor: new stylus.nodes.RGBA(51, 197, 255, 1),
},
},
scss: {
importers: [
// ...
],
},
},
},
})
css.preprocessorOptions[extension].additionalData
- Type:
string | ((source: string, filename: string) => (string | { content: string; map?: SourceMap }))
This option can be used to inject extra code for each style content. Note that if you include actual styles and not just variables, those styles will be duplicated in the final bundle.
Example:
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `$injectedColor: orange;`,
},
},
},
})
::: tip Importing files Since the same code is prepended to files in different directories, relative paths won't resolve correctly. Use absolute paths or aliases instead. :::
css.preprocessorMaxWorkers
- Type:
number | true - Default:
true
Specifies the maximum number of threads CSS preprocessors can use. true means up to the number of CPUs minus 1. When set to 0, Vite will not create any workers and will run the preprocessors in the main thread.
Depending on the preprocessor options, Vite may run the preprocessors on the main thread even if this option is not set to 0.
css.devSourcemap
- Experimental: Give Feedback
- Type:
boolean - Default:
false
Whether to enable sourcemaps during dev.
css.transformer
- Experimental: Give Feedback
- Type:
'postcss' | 'lightningcss' - Default:
'postcss'
Selects the engine used for CSS processing. Check out Lightning CSS for more information.
::: info Duplicate @imports
Note that postcss (postcss-import) has a different behavior with duplicated @import from browsers. See postcss/postcss-import#462.
:::
css.lightningcss
- Experimental: Give Feedback
- Type:
import type {
CSSModulesConfig,
Drafts,
Features,
NonStandard,
PseudoClasses,
Targets,
} from 'lightningcss'
{
targets?: Targets
include?: Features
exclude?: Features
drafts?: Drafts
nonStandard?: NonStandard
pseudoClasses?: PseudoClasses
unusedSymbols?: string[]
cssModules?: CSSModulesConfig,
// ...
}
Configures Lightning CSS. Full transform options can be found in the Lightning CSS repo.
json.namedExports
- Type:
boolean - Default:
true
Whether to support named imports from .json files.
json.stringify
- Type:
boolean | 'auto' - Default:
'auto'
If set to true, imported JSON will be transformed into export default JSON.parse("...") which is significantly more performant than Object literals, especially when the JSON file is large.
If set to 'auto', the data will be stringified only if the data is bigger than 10kB.
oxc
- Type:
OxcOptions | false
OxcOptions extends Oxc Transformer's options. The most common use case is customizing JSX:
export default defineConfig({
oxc: {
jsx: {
runtime: 'classic',
pragma: 'h',
pragmaFrag: 'Fragment',
},
},
})
By default, transformation by Oxc is applied to ts, jsx and tsx files. You can customize this with oxc.include and oxc.exclude, which can be a regex, a picomatch pattern, or an array of either.
In addition, you can also use oxc.jsxInject to automatically inject JSX helper imports for every file transformed by Oxc:
export default defineConfig({
oxc: {
jsxInject: `import React from 'react'`,
},
})
Set to false to disable transformation by Oxc.
esbuild
- Type:
ESBuildOptions | false - Deprecated
This option is converted to oxc option internally. Use oxc option instead.
assetsInclude
- Type:
string | RegExp | (string | RegExp)[] - Related: Static Asset Handling
Specify additional picomatch patterns to be treated as static assets so that:
-
They will be excluded from the plugin transform pipeline when referenced from HTML or directly requested over
fetchor XHR. -
Importing them from JS will return their resolved URL string (this can be overwritten if you have a
enforce: 'pre'plugin to handle the asset type differently).
The built-in asset type list can be found here.
Example:
export default defineConfig({
assetsInclude: ['**/*.gltf'],
})
logLevel
- Type:
'info' | 'warn' | 'error' | 'silent'
Adjust console output verbosity. Default is 'info'.
customLogger
- Type:
interface Logger { info(msg: string, options?: LogOptions): void warn(msg: string, options?: LogOptions): void warnOnce(msg: string, options?: LogOptions): void error(msg: string, options?: LogErrorOptions): void clearScreen(type: LogType): void hasErrorLogged(error: Error | RollupError): boolean hasWarned: boolean }
Use a custom logger to log messages. You can use Vite's createLogger API to get the default logger and customize it to, for example, change the message or filter out certain warnings.
import { createLogger, defineConfig } from 'vite'
const logger = createLogger()
const loggerWarn = logger.warn
logger.warn = (msg, options) => {
// Ignore empty CSS files warning
if (msg.includes('vite:css') && msg.includes(' is empty')) return
loggerWarn(msg, options)
}
export default defineConfig({
customLogger: logger,
})
clearScreen
- Type:
boolean - Default:
true
Set to false to prevent Vite from clearing the terminal screen when logging certain messages. Via command line, use --clearScreen false.
envDir
- Type:
string | false - Default:
root
The directory from which .env files are loaded. Can be an absolute path, or a path relative to the project root. false will disable the .env file loading.
See here for more about environment files.
envPrefix
- Type:
string | string[] - Default:
VITE_
Env variables starting with envPrefix will be exposed to your client source code via import.meta.env.
:::warning SECURITY NOTES
envPrefix should not be set as '', which will expose all your env variables and cause unexpected leaking of sensitive information. Vite will throw an error when detecting ''.
If you would like to expose an unprefixed variable, you can use define to expose it:
define: {
'import.meta.env.ENV_VARIABLE': JSON.stringify(process.env.ENV_VARIABLE)
}
:::
appType
- Type:
'spa' | 'mpa' | 'custom' - Default:
'spa'
Whether your application is a Single Page Application (SPA), a Multi Page Application (MPA), or Custom Application (SSR and frameworks with custom HTML handling):
'spa': include HTML middlewares and use SPA fallback. Configure sirv withsingle: truein preview'mpa': include HTML middlewares'custom': don't include HTML middlewares
Learn more in Vite's SSR guide. Related: server.middlewareMode.
devtools
- Experimental: Give Feedback
- Type:
boolean|DevToolsConfig - Default:
false
Enable devtools integration for inspecting the dev server and analyzing builds.
Ensure that @vitejs/devtools is installed as a dependency. Install @vitejs/devtools-vite to inspect the Vite dev server and @vitejs/devtools-rolldown to enable build analysis. DevTools runs for both serve and build by default; use apply to limit it to either command.
Plugin config hooks cannot change the devtools option. Set it in the user config instead.
When installed, @vitejs/devtools provides the type definitions for this option:
import { defineConfig } from 'vite'
export default defineConfig({
devtools: {
apply: 'serve',
},
})
See Vite DevTools for more details.
tsconfig
- Type:
string
Path to the TypeScript configuration file used by Vite. Relative paths are resolved from the project root.
When this option is not set, Vite discovers the closest matching tsconfig.json for each file. See TypeScript Compiler Options for more details.
::: warning Prefer automatic discovery
Setting this option is discouraged because it overrides Vite's per-file tsconfig discovery which is aligned with TypeScript language server. Prefer placing a tsconfig.json near the files it configures and using TypeScript references for multi-project setups.
If the goal is to remap imports, prefer resolve.alias or the imports and exports fields in package.json instead of selecting a tsconfig solely for compilerOptions.paths. Use this option only when automatic discovery cannot identify the intended configuration.
:::
future
- Type:
Record<string, 'warn' | undefined> - Related: Breaking Changes
Enable future breaking changes to prepare for a smooth migration to the next major version of Vite. The list may be updated, added, or removed at any time as new features are developed.
See the Breaking Changes page for details of the possible options.
SSR Options
Unless noted, the options in this section are applied to both dev and build.
ssr.external
- Type:
string[] | true - Related: SSR Externals
Externalize the given dependencies and their transitive dependencies for SSR. By default, all dependencies are externalized except for linked dependencies (for HMR). If you prefer to externalize the linked dependency, you can pass its name to this option.
If true, all dependencies including linked dependencies are externalized.
Note that the explicitly listed dependencies (using string[] type) will always take priority if they're also listed in ssr.noExternal (using any type).
ssr.noExternal
- Type:
string | RegExp | (string | RegExp)[] | true - Related: SSR Externals
Prevent listed dependencies from being externalized for SSR, which they will get bundled in build. By default, only linked dependencies are not externalized (for HMR). If you prefer to externalize the linked dependency, you can pass its name to the ssr.external option.
If true, no dependencies are externalized. However, dependencies explicitly listed in ssr.external (using string[] type) can take priority and still be externalized. If ssr.target: 'node' is set, Node.js built-ins will also be externalized by default.
Note that if both ssr.noExternal: true and ssr.external: true are configured, ssr.noExternal takes priority and no dependencies are externalized.
ssr.target
- Type:
'node' | 'webworker' - Default:
node
Build target for the SSR server.
ssr.resolve.conditions
- Type:
string[] - Default:
['module', 'node', 'development|production'](defaultServerConditions) (['module', 'browser', 'development|production'](defaultClientConditions) forssr.target === 'webworker') - Related: Resolve Conditions
These conditions are used in the plugin pipeline, and only affect non-externalized dependencies during the SSR build. Use ssr.resolve.externalConditions to affect externalized imports.
ssr.resolve.externalConditions
- Type:
string[] - Default:
['node', 'module-sync']
Conditions that are used during ssr import (including ssrLoadModule) of externalized direct dependencies (external dependencies imported by Vite).
:::tip
When using this option, make sure to run Node with --conditions flag with the same values in both dev and build to get a consistent behavior.
For example, when setting ['node', 'custom'], you should run NODE_OPTIONS='--conditions custom' vite in dev and NODE_OPTIONS="--conditions custom" node ./dist/server.js after build.
:::
ssr.resolve.mainFields
- Type:
string[] - Default:
['module', 'jsnext:main', 'jsnext']
List of fields in package.json to try when resolving a package's entry point. Note this takes lower precedence than conditional exports resolved from the exports field: if an entry point is successfully resolved from exports, the main field will be ignored. This setting only affects non-externalized dependencies.
Worker Options
Unless noted, the options in this section are applied to all dev, build, and preview.
worker.format
- Type:
'es' | 'iife' - Default:
'iife'
Output format for worker bundle.
worker.plugins
Vite plugins that apply to the worker bundles. Note that config.plugins only applies to workers in dev, it should be configured here instead for build.
The function should return new plugin instances as they are used in parallel rolldown worker builds. As such, modifying config.worker options in the config hook will be ignored.
worker.rolldownOptions
- Type:
RolldownOptions
Rolldown options to build worker bundle.
worker.rollupOptions
- Type:
RolldownOptions - Deprecated
This option is an alias of worker.rolldownOptions option. Use worker.rolldownOptions option instead.