A Vite config I actually understand
My build config had become a haunted house — options copied from blog posts, plugins added to fix errors I no longer remembered, comments that lied. So I deleted it and started from an empty file, adding back only what I could justify out loud. Here’s what survived.
Start with nothing
Vite’s defaults are genuinely good. The honest starting point is an empty object, and most projects never need much more.
import { defineConfig } from "vite";
export default defineConfig({});
Everything below is something I added because a real need showed up — not preemptively.
Path aliases, because relative imports rot
The one quality-of-life change I add to every project. ../../../ is a refactoring hazard; a @ alias is stable.
import { defineConfig } from "vite";
import { fileURLToPath, URL } from "node:url";
export default defineConfig({
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
If you use TypeScript, mirror this in tsconfig.json under compilerOptions.paths or the editor won’t follow it.
A dev server that fails loudly
Two settings save real time. strictPort stops Vite from silently hopping to a different port when 5173 is taken — I’d rather know. And explicit proxy rules keep API calls same-origin in dev so cookies and CORS behave like production.
server: {
strictPort: true,
proxy: {
'/api': { target: 'http://localhost:8787', changeOrigin: true },
},
},
Build options worth their weight
I only touch the build config when a bundle analysis tells me to. The two that earned a place:
build.sourcemap— on for staging, off for production unless I’m chasing a specific bug. Sourcemaps are big and you rarely want them public.- Manual chunks — only after measuring. Splitting a genuinely large, rarely-changing dependency into its own chunk improves cache hit rates across deploys.
build: {
sourcemap: false,
rollupOptions: {
output: {
manualChunks: { vendor: ['react', 'react-dom'] },
},
},
},
Every manual chunk is a bet that a dependency changes less often than your app code. Make that bet on purpose, with numbers — not by reflex.
The rule I kept
For each line I asked: what breaks if I delete this? If I couldn’t answer, it went. The config that’s left is short, boring, and — for the first time in years — something I can read top to bottom and actually understand.