vite
Original:🇺🇸 English
Translated
Configure and optimize Vite 7 for React projects. Covers build tooling, dev server, plugins, HMR, chunk splitting, Environment API, and Rolldown integration. Use when setting up Vite, configuring builds, optimizing bundles, managing plugins, or troubleshooting dev server. Triggers on vite, vite config, vite plugin, HMR, dev server, build optimization, chunk splitting, rolldown, vite proxy, environment api, rolldown-vite.
1installs
Sourcetenequm/skills
Added on
NPX Install
npx skill4agent add tenequm/skills viteTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Vite 7
Build tooling and dev server for React projects. Vite 7 (June 2025) is ESM-only, requires Node.js 20.19+ / 22.12+, and defaults browser target to . The user's stack uses (Rust-based drop-in replacement), , , , , and .
baseline-widely-availablerolldown-vite@vitejs/plugin-react@tailwindcss/vite@tanstack/router-plugin@cloudflare/vite-plugin@tanstack/react-startCritical Rules
Plugin Order Matters
TanStack Start or TanStack Router plugin MUST come before :
@vitejs/plugin-reactts
plugins: [
tanstackStart(), // or tanstackRouter() for SPA
tailwindcss(),
react(), // ALWAYS last among framework plugins
]Wrong order causes route generation failures and HMR breakage.
Vite 7 is ESM-Only
Vite 7 distributes as ESM only. Your must use / syntax. CJS is not supported in config files. Node.js 20.19+ supports natively, so Vite can still be required by CJS consumers.
vite.config.tsimportexportrequire()require(esm)No tailwind.config.js
tailwind.config.jsTailwind CSS v4 uses CSS-first configuration. Never create /. Use plugin and configure in CSS via , , .
tailwind.config.jstailwind.config.ts@tailwindcss/vite@theme@utility@pluginEnvironment Variables Need VITE_ Prefix
Only variables prefixed with are exposed to client code via . Server-only secrets must NOT use this prefix. For type safety, augment in .
VITE_import.meta.envImportMetaEnvvite-env.d.tssplitVendorChunkPlugin Is Removed
Removed in Vite 7. Use for custom chunk splitting.
build.rollupOptions.output.manualChunksConfiguration
vite.config.ts (Full Stack with TanStack Start)
ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { cloudflare } from '@cloudflare/vite-plugin'
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
tanstackStart(),
cloudflare(),
tailwindcss(),
react(),
],
resolve: {
alias: {
'@': new URL('./src', import.meta.url).pathname,
},
},
})vite.config.ts (SPA with TanStack Router)
ts
import { defineConfig } from 'vite'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
tanstackRouter({ autoCodeSplitting: true }),
tailwindcss(),
react(),
],
resolve: {
alias: {
'@': new URL('./src', import.meta.url).pathname,
},
},
})React Compiler
ts
react({
babel: {
plugins: [['babel-plugin-react-compiler', {}]],
},
})Install: . Auto-memoizes components and hooks - no manual /.
pnpm add -D babel-plugin-react-compileruseMemouseCallbackPath Aliases
Use for ESM-compatible resolution (no in ESM):
import.meta.url__dirnamets
resolve: {
alias: {
'@': new URL('./src', import.meta.url).pathname,
},
}Mirror in :
tsconfig.json"paths": { "@/*": ["./src/*"] }Environment Variables
Files: , , , . Only -prefixed vars exposed to client. Built-in constants: , , , , .
.env.env.local.env.[mode].env.[mode].localVITE_import.meta.env.MODE.DEV.PROD.SSR.BASE_URLType augmentation in :
src/vite-env.d.tsts
interface ImportMetaEnv {
readonly VITE_API_URL: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}Plugin Ecosystem
@vitejs/plugin-react
Provides Fast Refresh (HMR for React), JSX transform, and optional Babel plugin pipeline. Always place last among framework plugins.
ts
import react from '@vitejs/plugin-react'
react() // zero-config default
react({ fastRefresh: false }) // disable for debugging HMR issues@tailwindcss/vite
Native Vite integration for Tailwind CSS v4. Replaces PostCSS-based setup - no needed.
postcss.config.jsts
import tailwindcss from '@tailwindcss/vite'
tailwindcss() // zero-config, reads @theme from CSS@tanstack/router-plugin/vite
File-based route generation for TanStack Router. Must come before .
react()ts
import { tanstackRouter } from '@tanstack/router-plugin/vite'
tanstackRouter({ autoCodeSplitting: true })@tanstack/react-start/plugin/vite
Full-stack plugin for TanStack Start. Includes router plugin internally - do NOT add both.
ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
tanstackStart() // default SSR
tanstackStart({ spa: { enabled: true } }) // SPA mode (no SSR)@cloudflare/vite-plugin
Runs Worker code inside during dev, matching production behavior. Uses Vite's Environment API for runtime integration.
workerdts
import { cloudflare } from '@cloudflare/vite-plugin'
cloudflare() // reads wrangler.jsonc by default
// Programmatic config (no wrangler file needed)
cloudflare({
config: {
name: 'my-worker',
compatibility_flags: ['nodejs_compat'],
},
})Dev Server
Proxy Configuration
ts
server: {
proxy: {
'/api': {
target: 'http://localhost:8787',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/ws': { target: 'ws://localhost:8787', ws: true },
},
}HMR Troubleshooting
| Symptom | Fix |
|---|---|
| Full reload instead of HMR | Check |
| HMR not connecting | Set |
| Stale state after edit | Component must export a single component |
| CSS not updating | Ensure |
Behind a reverse proxy:
ts
server: {
hmr: { protocol: 'ws', host: 'localhost', port: 5173, clientPort: 443 },
}File Warmup
ts
server: {
warmup: {
clientFiles: ['./src/components/*.tsx', './src/routes/__root.tsx'],
},
}Build Optimization
Default Browser Target
Vite 7 targets (Chrome 107+, Edge 107+, Firefox 104+, Safari 16+). Override: or .
baseline-widely-availablebuild.target: 'es2020'['chrome90', 'safari14']Manual Chunks
ts
build: {
rollupOptions: {
output: {
manualChunks: {
'react-vendor': ['react', 'react-dom'],
'tanstack': ['@tanstack/react-router', '@tanstack/react-query'],
},
},
},
}Dynamic splitting by function:
ts
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react')) return 'react-vendor'
if (id.includes('@tanstack')) return 'tanstack'
return 'vendor'
}
}Bundle Analysis
bash
pnpm add -D rollup-plugin-visualizerts
import { visualizer } from 'rollup-plugin-visualizer'
// Add to plugins array
visualizer({ filename: 'stats.html', open: true, gzipSize: true })See build-optimization.md for detailed chunking strategies, CSS splitting, asset inlining, source maps, and performance tuning.
Rolldown Integration
What is rolldown-vite
rolldown-viteRolldown will become the default bundler in Vite 8 (currently in beta). Using today prepares your project for the transition.
rolldown-viteNote: Vite 7 requires Vitest 3.2+ for compatibility. Earlier Vitest versions will not work.
Installation
In , alias to :
package.jsonviterolldown-vitejson
{
"devDependencies": {
"vite": "npm:rolldown-vite@latest"
}
}For monorepos or frameworks with Vite as a peer dependency, use overrides:
json
{
"pnpm": {
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}
}Then run . No config changes needed - it is a drop-in replacement.
pnpm installKey Differences from Standard Vite
- No esbuild dependency - Oxc handles all transforms and minification (config still shows but the underlying engine is Oxc)
minify: 'esbuild' - Faster builds - Rust-native bundling, especially for large projects
- Same plugin API - Rollup/Vite plugins work without changes in most cases
- Patch versions may break - follows Vite major/minor but patches are independent
rolldown-vite
Compatibility Notes
Most frameworks and Vite plugins work out of the box. Check the rolldown-vite repo for known issues and changelog. Some warnings about unsupported options may appear during the transition period.
Environment API
Experimental API introduced in Vite 6, improved in Vite 7 with the hook. Enables multi-target builds (browser, Node.js, edge runtimes) from a single Vite config.
buildAppHow It Works
Each environment has its own module graph, plugin pipeline, and build config. The uses this to run Worker code inside during dev, matching production behavior.
@cloudflare/vite-pluginworkerdbuildApp Hook (Vite 7)
Frameworks coordinate building multiple environments. Config-level form (most common):
ts
export default defineConfig({
builder: {
async buildApp(builder) {
await builder.build(builder.environments.client)
await builder.build(builder.environments.server)
},
},
})Plugin hook form (for plugin authors):
ts
{
name: 'my-framework',
buildApp: async (builder) => {
const environments = Object.values(builder.environments)
return Promise.all(
environments.map((env) => builder.build(env))
)
},
}Multi-Environment Config
ts
export default defineConfig({
environments: {
client: {
build: { outDir: 'dist/client' },
},
server: {
build: { outDir: 'dist/server' },
},
},
})For most projects, the or handles environment configuration automatically. Direct Environment API usage is for framework authors.
@cloudflare/vite-plugin@tanstack/react-startDeployment
Cloudflare Workers (via TanStack Start)
Add to plugins and create :
cloudflare()wrangler.jsoncjsonc
// wrangler.jsonc
{
"name": "my-app",
"compatibility_date": "2025-01-01",
"compatibility_flags": ["nodejs_compat"],
"main": "./dist/server/index.js",
"assets": { "directory": "./dist/client" }
}bash
pnpm vite build && pnpm wrangler deployStatic SPA
Build produces . Deploy to any static host (Cloudflare Pages, Vercel, Netlify).
dist/Prerendering (SSG)
ts
tanstackStart({ prerender: { enabled: true, crawlLinks: true } })Best Practices
- Plugin order - framework plugins first, then utilities, then last
react() - Use rolldown-vite - drop-in replacement with 3-16x faster builds
- Set in dev - avoid unnecessary refetches during HMR reloads
staleTime - Warm up critical files - use for frequently accessed modules
server.warmup - Split vendor chunks - separate ,
reactinto stable chunks for caching@tanstack/* - Never use - specific properties only for CSS transitions
transition-all - Use for path resolution in ESM config files
import.meta.url - Analyze bundles regularly - use before deploys
rollup-plugin-visualizer - Keep prefix discipline - only public values; secrets go in server functions
VITE_ - Set for production -
build.sourcemapfor error tracking without exposing source'hidden'
Resources
- Vite Docs: https://vite.dev/guide/
- Vite 7 Blog: https://vite.dev/blog/announcing-vite7
- Migration Guide: https://vite.dev/guide/migration
- Build Options: https://vite.dev/config/build-options
- Server Options: https://vite.dev/config/server-options
- Env Variables: https://vite.dev/guide/env-and-mode
- Rolldown-Vite: https://voidzero.dev/posts/announcing-rolldown-vite
- Cloudflare Vite Plugin: https://developers.cloudflare.com/workers/vite-plugin/
- Plugin React: https://github.com/vitejs/vite-plugin-react
- GitHub: https://github.com/vitejs/vite