Vite 6 ships with sensible defaults that cover most projects with near-zero config. But the real power comes from knowing which knobs exist and which ones are actually worth turning. This guide covers the configuration options you will reach for on real projects — not a dump of every option, but the ones that matter.
What changed in 2026
- Vite 6 introduced the Environment API, giving first-class support for multiple render environments (client, SSR, Edge) in a single config.
- Rollup 4 (the default bundler) brought faster native builds via the
@rollup/wasm-node package — no Node.js plugin compilation step.
optimizeDeps is now smarter about pre-bundling — false positives in dev are rare, and you rarely need to override it manually.
@vitejs/plugin-react switched to the automatic JSX runtime by default; you no longer import React in every file.
- Lightning CSS became the recommended CSS transformer, replacing PostCSS for most projects.
Basic structure
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: { '@': resolve(__dirname, 'src') },
},
})
Path aliases
The most common config addition. Once set, import from @/components/Button instead of ../../components/Button.
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@assets': resolve(__dirname, 'src/assets'),
'@lib': resolve(__dirname, 'src/lib'),
},
},
Also update tsconfig.json so TypeScript agrees:
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@assets/*": ["./src/assets/*"]
}
}
}
Environment variables
// .env.local
VITE_API_URL=http://localhost:3000
DATABASE_URL=postgres://... # NOT exposed to the browser
Access in code:
const apiUrl = import.meta.env.VITE_API_URL
const isProd = import.meta.env.PROD
Use envPrefix in config to change the prefix from VITE_:
envPrefix: 'APP_', // now APP_API_URL is exposed, not VITE_API_URL
Dev server proxy
Avoids CORS issues during development by forwarding /api requests to your backend:
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
},
},
},
Build configuration
build: {
target: 'es2022', // modern browsers only in 2026
sourcemap: true,
minify: 'esbuild', // default, fast
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
},
},
},
},
Common config options table
| Option |
Default |
Change when |
server.port |
5173 |
Port conflict |
server.open |
false |
Auto-open browser on dev start |
build.target |
modules |
Need specific browser compat |
build.outDir |
dist |
Different deploy convention |
build.sourcemap |
false |
Need production debugging |
base |
/ |
Deploying to a sub-path |
preview.port |
4173 |
Preview server port |
Useful plugins in 2026
| Plugin |
Purpose |
@vitejs/plugin-react |
React fast refresh + JSX |
vite-plugin-svgr |
Import SVGs as React components |
unplugin-icons |
On-demand icon imports |
vite-bundle-visualizer |
Interactive bundle size chart |
vite-plugin-pwa |
PWA manifest + service worker |
How to pick build targets
| Audience |
build.target |
| Modern evergreen only |
es2022 or esnext |
| Enterprise with older Edge |
es2019 |
| Need broad support |
['es2015', 'chrome58', 'safari11'] |
Common mistakes
Forgetting tsconfig.json paths — you set the alias in Vite but TypeScript still complains. Both files need the alias entry.
Hard-coding localhost in code instead of env vars — any URL that changes per environment belongs in .env.* files.
Over-splitting chunks — manualChunks with too many entries creates too many HTTP requests. 2–4 chunks (vendor, router, app) is usually optimal.
Using NODE_ENV directly — in Vite, use import.meta.env.MODE and import.meta.env.PROD/DEV instead of process.env.NODE_ENV.
What to skip
- Custom PostCSS pipeline unless you have a specific plugin requirement — Lightning CSS handles nesting, prefixing, and minification faster.
vite-plugin-legacy for modern projects — the polyfill weight is not worth it if your users are on modern browsers (which most are in 2026).
- Ejecting to a custom Rollup config —
build.rollupOptions gives you all the control you need without leaving the Vite abstraction.
FAQ
Can Vite build library packages?
Yes. Set build.lib with an entry point, and Vite outputs ESM and CJS with correct external declarations. Most component library authors use this.
How do I add absolute imports without TypeScript?
Set resolve.alias in the Vite config only. TypeScript paths is needed for type-checking, not for the actual build.
Does Vite support multi-page apps?
Yes — set build.rollupOptions.input to an object mapping page names to HTML file paths, and Vite builds all of them.
What replaces create-react-app in 2026?
npm create vite@latest is the standard answer. It scaffolds React, Vue, Svelte, Solid, and Vanilla with TypeScript support in under a minute.
Where to go next