vite-v8
Vite 8 Skill
Configure, migrate, and debug Vite 8 projects with the repo's preferred Vite-native patterns.
Before You Start
This skill focuses on the Vite 8 architecture shift, not generic bundler advice.
| Metric | Without Skill | With Skill |
|---|---|---|
| Migration Time | ~120 min | ~40 min |
| Common Config Errors | 6+ | 0 |
| Token Usage | High (trial/error) | Low (known patterns) |
Known Issues This Skill Prevents
- Broken builds from leaving
rollupOptionsin Vite 8 configs whererolldownOptionsis needed - Outdated JS/TS transform setup from using
esbuildinstead ofoxc - Plugin code checking stale
ssrbooleans instead of environment-aware APIs - HMR bugs from using deprecated
handleHotUpdatepatterns instead ofhotUpdate - SSR/runtime confusion from older
ssrLoadModulemental models instead of Module Runner - Performance regressions from missing hook filters in Rust↔JS plugin boundaries
- Slow startup and request waterfalls from barrel files, missing warmup, or loose import resolution
Quick Start
Step 1: Start with a typed Vite 8 config
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
server: {
port: 5173,
},
build: {
target: 'baseline-widely-available',
rolldownOptions: {
output: {
manualChunks: undefined,
},
},
},
});
Why this matters: Vite 8 is built around Rolldown/Oxc-era config and defaults. Starting from defineConfig with Vite 8 options avoids backporting old Rollup/esbuild assumptions into a new architecture.
Step 2: Prefer Vite 8 terminology in plugins and SSR code
import type { Plugin } from 'vite';
export function inspectEnvironment(): Plugin {
return {
name: 'inspect-environment',
configEnvironment(name) {
if (name === 'ssr') {
return {
resolve: {
conditions: ['node'],
},
};
}
},
};
}
Why this matters: Vite 8 leans on named environments and environment-aware plugin behavior. That is a better fit than older client-vs-SSR shortcuts.
Step 3: Use the correct one-shot commands
vite dev
vite build
vite build --ssr src/entry-server.ts
vite preview
Why this matters: These are the stable command surfaces agents and CI flows should target. Avoid inventing framework-specific abstractions unless the project already uses them.
Critical Rules
Always Do
- Use
vite.config.tswithdefineConfigfor repo-facing Vite 8 work - Prefer
build.rolldownOptionsover legacybuild.rollupOptions - Prefer
oxcoveresbuildfor new Vite 8 transform configuration - Use named environments when plugin or SSR behavior differs by runtime
- Use hook filters when writing performance-sensitive
transformorresolveIdplugins - Reach for Module Runner concepts when debugging modern SSR/runtime execution
- Use explicit file extensions and review barrel files when performance work matters
- Keep Vite plugin code ESM-first
Never Do
- Never introduce new
rollupOptions/esbuildexamples as the preferred Vite 8 path - Never treat
handleHotUpdateas the forward-looking HMR hook in Vite 8 - Never assume a single client/SSR split is enough for all runtimes
- Never suggest CommonJS config as the default for new Vite work
- Never skip
ssr.noExternalreview when SSR dependencies misbehave
Common Mistakes
Wrong - legacy build config:
export default defineConfig({
build: {
rollupOptions: {
external: ['react'],
},
},
esbuild: {
jsxInject: "import React from 'react'",
},
});
Correct - Vite 8 config:
export default defineConfig({
build: {
rolldownOptions: {
external: ['react'],
},
},
oxc: {
jsxInject: "import React from 'react'",
},
});
Why: Vite 8 moved its preferred build and transform configuration surface to Rolldown and Oxc.
Wrong - stale HMR hook:
export default function plugin() {
return {
name: 'old-hmr',
handleHotUpdate(ctx) {
return ctx.modules;
},
};
}
Correct - environment-aware HMR:
export default function plugin() {
return {
name: 'env-hmr',
hotUpdate(ctx) {
return ctx.modules;
},
};
}
Why: hotUpdate is the environment-aware Vite 8 direction, while handleHotUpdate is legacy-oriented.
Known Issues Prevention
| Issue | Root Cause | Solution |
|---|---|---|
| Config migration stalls | Old Rollup/esbuild settings copied forward | Migrate to rolldownOptions and oxc |
| Plugin logic breaks in non-standard runtimes | Plugin assumes only client/SSR | Use named environments and this.environment |
| HMR customization feels brittle | Legacy HMR hook carried forward | Prefer hotUpdate and environment-aware flows |
| SSR dependency crashes | Externalization assumptions are wrong | Review ssr.noExternal and runtime-specific needs |
| Dev/build behavior diverges | Config ignores Vite 8's unified engine model | Validate both vite dev and vite build under Rolldown |
| Plugin performance drops | Too much JS-side hook work | Add hook filters and narrower matching |
| Cold starts are sluggish | Heavy hot paths are not warmed and import graph is noisy | Review server.warmup, explicit extensions, and barrel-file usage |
Bundled Resources
References
- Core config and CLI patterns →
references/core-config-reference.md - Environment-aware plugin authoring →
references/plugin-environment-reference.md - Build, SSR, and migration guidance →
references/build-ssr-migration-reference.md - Performance and dev-server heuristics →
references/performance-devserver-reference.md - Reference index →
references/README.md
Configuration Reference
vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
build: {
target: 'baseline-widely-available',
rolldownOptions: {
output: {
chunkFileNames: 'assets/[name]-[hash].js',
},
},
},
oxc: {
jsxInject: "import React from 'react'",
},
environments: {
ssr: {
resolve: {
conditions: ['node'],
},
},
},
css: {
lightningcss: {},
},
});
Key settings:
build.rolldownOptions: Preferred Vite 8 build customization surfaceoxc: Preferred JS/TS transform configuration surface in new Vite 8 examplesenvironments: Use when runtime behavior differs across client/SSR/edge-like targetscss.lightningcss: Reflects Vite 8's modern CSS processing directionserver.warmup: Useful in large apps where cold-start waterfalls hit the same hot files repeatedly
Project Structure
my-app/
├── src/
├── index.html
├── vite.config.ts
├── package.json
└── tsconfig.json
Why this matters: Vite 8 still rewards simple, explicit project layout. Complexity should come from runtime environments and plugin boundaries, not from hiding the core config.
Performance heuristic: If startup feels bad, inspect import-graph shape before chasing exotic bundler flags. Barrel files, omitted extensions, and lack of warmup often matter more than another layer of config cleverness.
Common Patterns
Environment-aware plugin pattern
import type { Plugin } from 'vite';
export function envAwarePlugin(): Plugin {
return {
name: 'env-aware-plugin',
transform: {
filter: {
id: /\.(ts|tsx)$/,
},
handler(code, id) {
return {
code,
map: null,
};
},
},
configEnvironment(name) {
if (name === 'ssr') {
return {
resolve: {
conditions: ['node'],
},
};
}
},
};
}
SSR build pattern
vite build
vite build --ssr src/entry-server.ts
vite preview
Module Runner mental model
// Pseudocode sketch
const mod = await moduleRunner.import('/src/entry-server.ts');
Use this model when modern Vite SSR debugging is really about runtime execution boundaries rather than plain bundling.
Dependencies
Required
| Package | Version | Purpose |
|---|---|---|
vite |
^8 | Build tool, dev server, plugin host |
node |
>=20.19 or >=22.12 | Required Vite 8 runtime |
Optional
| Package | Version | Purpose |
|---|---|---|
typescript |
latest | Typed vite.config.ts and plugin authoring |
| framework plugin packages | latest | React/Vue/Svelte/etc integrations |
Official Documentation
Troubleshooting
Old config keys no longer feel right
Symptoms: A config works but reads like pre-Vite-8 code, or new options are not behaving as expected.
Solution:
build: {
rolldownOptions: {},
}
oxc: {}
SSR runtime behavior is unclear
Symptoms: The bundle builds, but runtime execution differs by environment or platform.
Solution:
Review environments, this.environment, Module Runner expectations, and ssr.noExternal before changing unrelated bundler settings.
Plugin hook work feels slow or noisy
Symptoms: Custom plugins add overhead in dev or build.
Solution: Use hook filters and narrow matching patterns so only relevant files cross the Rust↔JS boundary.
Setup Checklist
Before using this skill, verify:
-
viteis on a Vite 8 release line - Node satisfies Vite 8 runtime requirements
-
vite.config.tsis ESM/TypeScript-first - Legacy
rollupOptions/esbuildusage has been reviewed - Environment-specific behavior is modeled explicitly when SSR/edge runtimes are involved