Vite Build Error? Fix Chunk Size Warnings, Module Errors, and More
Troubleshoot the most common vite build failures — chunk size exceeded, Cannot find module, missing env vars, broken aliases, and Vite 4→5 migration breaks.
Common errors and fixes
1. Chunk size exceeds limit warning
The build succeeds but prints a warning in yellow. Vite's default chunkSizeWarningLimit is 500 KB. Large vendor bundles (React, lodash, date-fns) are the usual culprit. The real fix is to split them out, not just silence the warning.
(!) Some chunks are larger than 500 kB after minification.
dist/assets/index-Cba3kL9r.js 892.34 kB Option A — manualChunks (recommended): split node_modules into a separate vendor chunk so the browser can cache it independently:
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
}
}
}
}
}; Option B — dynamic imports: for route-level code splitting, use import() instead of static import so each route becomes its own chunk:
// Before (puts everything in main chunk)
import HeavyChart from './HeavyChart';
// After (lazy-loaded separate chunk)
const HeavyChart = lazy(() => import('./HeavyChart')); Option C — raise the warning limit (only if code splitting is not possible):
// vite.config.js — suppresses the warning, does not fix the bundle size
export default {
build: {
chunkSizeWarningLimit: 1000 // KB
}
}; 2. Cannot find module in build but not in dev
vite dev uses Node resolution at serve time; vite build uses Rollup which resolves modules at bundle time with different rules. The most common cause: path aliases in tsconfig.json that are not mirrored in vite.config.js.
// tsconfig.json — only affects TypeScript type checking
{
"compilerOptions": {
"paths": {
"@components/*": ["./src/components/*"]
}
}
}
// vite.config.js — MUST mirror every alias from tsconfig for the build
import { defineConfig } from 'vite';
import path from 'path';
export default defineConfig({
resolve: {
alias: {
'@components': path.resolve(__dirname, './src/components')
}
}
}); new URL('./image.png', window.location.href) — use new URL('./image.png', import.meta.url) so Rollup can resolve and hash the asset path at build time.
- CommonJS packages: packages that export only
require()need@rollup/plugin-commonjs— Vite includes it by default foroptimizeDepsbut some edge cases still require explicit configuration. - Peer dependency conflicts: if
npm installfails with ERESOLVE, usenpm install --legacy-peer-deps. With pnpm, addshamefully-hoist=trueto.npmrc.
3. Environment variables undefined after build
Vite statically replaces import.meta.env.VITE_* at build time. Variables without the VITE_ prefix are intentionally omitted from the client bundle. process.env does not exist in the browser and will throw at runtime.
# .env — variables without VITE_ prefix are server-only (safe, never bundled)
DATABASE_URL=postgres://user:pass@host/db
SECRET_KEY=my-secret
# .env — variables WITH VITE_ prefix are inlined into the browser bundle
VITE_API_URL=https://api.example.com
VITE_PUBLIC_KEY=pk_live_abc123 // WRONG — process.env is undefined in the browser after build
const apiUrl = process.env.API_URL;
// CORRECT
const apiUrl = import.meta.env.VITE_API_URL; - Mode files:
.env.productionis loaded forvite build,.env.developmentforvite dev— ensure the variable exists in the right file. - SSR builds: in SSR mode,
process.envworks on the server side only — do not use it in code that runs in both environments.
4. Base path config for non-root deployments
If your app deploys to a sub-path like https://example.com/app/, asset URLs in dist/ will point to /assets/index.js instead of /app/assets/index.js and the page will load blank. Set base in your config:
// vite.config.js
export default defineConfig({
base: '/app/', // trailing slash required
}); - GitHub Pages: set
base: '/repo-name/'— GitHub Pages serves projects atusername.github.io/repo-name/by default. - Access in code: use
import.meta.env.BASE_URLinside your app to construct absolute links that respect the base setting.
5. Vite 4 → 5 breaking changes
Upgrading from Vite 4 to Vite 5 can break builds silently. The most impactful changes:
- resolve.conditions: the
browsercondition is now always included for non-SSR builds. Some packages that relied on the absence of this condition will resolve to their browser build unexpectedly — setresolve.conditions: []to restore old behavior. - Worker format: Web Workers now default to
{ format: 'es' }. If your target environment does not support ES module workers, addworker: { format: 'iife' }to your Vite config. - Node 18+ required: Vite 5 dropped support for Node 14 and 16. If your CI pipeline pins an older Node version, the build will fail at startup with an unclear error.
- CJS server API removed: the CommonJS build of Vite's server API (
require('vite')) was removed — programmatic usage must use ESM (import { createServer } from 'vite').
# Check which Vite version you are running
npx vite --version
# Upgrade to latest Vite 5
npm install vite@latest --save-dev Know when your build infrastructure has an outage
Monitor npm, Vercel, Netlify, and GitHub Actions — free email alerts, no credit card.
FAQ
How do I fix the Vite chunk size warning?
Add manualChunks in build.rollupOptions.output to split node_modules into a vendor chunk, or use dynamic import() for route-level code splitting. As a last resort, raise build.chunkSizeWarningLimit.
Why does "Cannot find module" appear in vite build but not vite dev?
Path aliases in tsconfig.json must be mirrored in vite.config.js resolve.alias — Rollup does not read tsconfig.json. Also use import.meta.url for asset references instead of __dirname.
Why are my environment variables undefined after vite build?
Vite only exposes variables with the VITE_ prefix to the browser. Rename your variable to VITE_MY_VAR and access it as import.meta.env.VITE_MY_VAR — never use process.env in client-side code.
What changed from Vite 4 to Vite 5 that breaks builds?
Key breaking changes: resolve.conditions defaults changed; Worker format defaults to ES modules; Node.js 14/16 no longer supported; CommonJS server API removed. Check the Vite 5 migration guide and ensure Node 18+ in your CI environment.