.claude/skills/vite/vite-errors/vite-errors-dependency/SKILL.md
Use when encountering pre-bundling errors, dependency resolution failures, stale cache issues, or slow development server startup. Prevents excluding CJS dependencies from pre-bundling (which breaks runtime module resolution) and misconfiguring optimizeDeps. Covers CJS/ESM conversion failures, missing dependency auto-discovery, optimizeDeps configuration, monorepo linked dependencies, cache invalidation, browser cache staleness, and large dependency tree performance. Keywords: pre-bundling, optimizeDeps, CJS, ESM, cache, dependency resolution, monorepo, node_modules/.vite.
npx skillsauth add OpenAEC-Foundation/OpenAEC-Workspace-Composer vite-errors-dependencyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Vite pre-bundles dependencies in dev mode ONLY. It converts CJS/UMD packages to ESM and collapses large dependency trees into single modules. The cache lives at node_modules/.vite.
| Version | Pre-Bundling Engine | Config Key for Engine Options |
|---------|--------------------|-----------------------------|
| Vite 5 | esbuild | optimizeDeps.esbuildOptions |
| Vite 6–7 | esbuild | optimizeDeps.esbuildOptions |
| Vite 8 | Rolldown | optimizeDeps.rolldownOptions |
NEVER assume pre-bundling affects production builds. Production uses Rollup (v5–v7) or Rolldown (v8) natively with @rollup/plugin-commonjs or built-in CJS support.
NEVER exclude a CJS dependency from pre-bundling via optimizeDeps.exclude. The browser cannot load CommonJS modules natively. Excluding a CJS package breaks module resolution at runtime.
NEVER edit files inside node_modules/ without also clearing the Vite cache (node_modules/.vite) and using --force. The browser aggressively caches pre-bundled deps with max-age=31536000,immutable.
ALWAYS add linked monorepo dependencies that do NOT export ESM to optimizeDeps.include. Vite skips pre-bundling for linked deps by default, assuming they are ESM source code.
ALWAYS restart the dev server with --force after modifying linked dependency source code in a monorepo.
Dev server error or unexpected behavior with a dependency?
│
├─ Error: "Failed to resolve import" or "does not provide an export named"
│ ├─ Is the package CJS-only?
│ │ ├─ YES → Is it in optimizeDeps.exclude?
│ │ │ ├─ YES → REMOVE it from exclude. CJS MUST be pre-bundled.
│ │ │ └─ NO → Add to optimizeDeps.include explicitly.
│ │ └─ NO (ESM) → Check package.json "exports" field for correct conditions.
│ │
│ └─ Is it a monorepo linked dep?
│ ├─ Does it export ESM? → No action needed (Vite treats as source).
│ └─ Does it export CJS? → Add to optimizeDeps.include.
│
├─ Error: "Outdated pre-bundle" or stale module content
│ ├─ Did you manually edit node_modules/?
│ │ ├─ YES → Run: vite --force AND clear browser cache.
│ │ └─ NO → Delete node_modules/.vite, restart dev server.
│ └─ Check: Did lockfile, vite.config, NODE_ENV, or patches change?
│ └─ YES → Vite should auto-invalidate. If not, run: vite --force.
│
├─ Slow dev server startup (many HTTP requests)
│ ├─ Check Network tab: hundreds of requests to one dependency?
│ │ └─ YES → Add that dependency to optimizeDeps.include.
│ │ Example: lodash-es triggers 600+ module requests without pre-bundling.
│ └─ Check: Are there undiscovered deps from plugin transforms?
│ └─ YES → Add to optimizeDeps.include (auto-discovery misses these).
│
└─ Import works in dev but fails in production (or vice versa)
└─ Pre-bundling is dev-only. Production uses a different CJS handling path.
Check build output for CJS interop issues separately.
| Symptom | Cause | Fix |
|---------|-------|-----|
| does not provide an export named 'X' from CJS package | CJS module uses module.exports — named ESM imports fail | Add package to optimizeDeps.include; use import pkg from 'pkg' then destructure |
| Failed to resolve import "X" for plugin-generated import | Auto-discovery crawls source only — plugin transforms are invisible | Add the dependency to optimizeDeps.include explicitly |
| optimizeDeps.exclude breaks a CJS package | Excluded CJS is served raw — browser cannot parse require() | REMOVE the package from exclude. NEVER exclude CJS deps |
| Linked monorepo dep throws ESM errors | Vite treats linked deps as source but the dep exports CJS | Add linked dep to optimizeDeps.include |
| Stale module content after editing node_modules/ | Browser cache holds immutable pre-bundled version | Run vite --force, disable browser cache in DevTools, reload |
| Dev server re-bundles on every start | Config, lockfile, or NODE_ENV changes between starts | Stabilize config; check for CI/env variable differences |
| 600+ HTTP requests on page load for one import | ESM dependency has many internal modules (e.g., lodash-es) | Add to optimizeDeps.include to collapse into single module |
| Uncaught TypeError: X is not a function | ESM interop incorrectly wraps default export | Add package to optimizeDeps.needsInterop (experimental) |
| Pre-bundling runs but changes not picked up | node_modules/.vite cache is stale | Delete node_modules/.vite directory OR run vite --force |
| Import works in dev, fails in production | Dev uses pre-bundling (esbuild/Rolldown); prod uses Rollup/Rolldown natively | Check build.commonjsOptions or CJS interop settings for production |
| Trigger | Automatic? | Description |
|---------|-----------|-------------|
| Package manager lockfile change | YES | package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb |
| vite.config.js relevant fields change | YES | Changes to optimizeDeps, resolve, plugins |
| NODE_ENV value change | YES | Switching between development/production/staging |
| Patches folder modification time | YES | Changes in patches/ directory (patch-package, pnpm patches) |
| Manual node_modules/ edits | NO | MUST run vite --force and clear browser cache manually |
| New dependency discovered at runtime | YES | Vite re-bundles and reloads the page automatically |
| Linked dep source code changes | NO | MUST restart dev server with --force |
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
optimizeDeps: {
include: [
'lodash-es', // Collapse 600+ internal modules
'linked-dep', // Monorepo CJS linked dep
'my-plugin > dep', // Dep imported via plugin transform
],
},
})
# CLI flag (recommended)
vite --force
# Manual deletion
rm -rf node_modules/.vite
export default defineConfig({
optimizeDeps: {
needsInterop: ['legacy-cjs-package'], // Experimental
},
})
// Vite 5–7: esbuild options
export default defineConfig({
optimizeDeps: {
esbuildOptions: {
target: 'es2020',
plugins: [/* esbuild plugins */],
},
},
})
// Vite 8: Rolldown options
export default defineConfig({
optimizeDeps: {
rolldownOptions: {
plugins: [/* Rolldown plugins */],
},
},
})
export default defineConfig({
optimizeDeps: {
noDiscovery: true, // Disable crawling
include: ['react', 'react-dom'], // Only optimize these
},
})
When pre-bundled deps appear stale in the browser:
vite --forcePre-bundled deps use HTTP header max-age=31536000,immutable with a version query string (?v=abc123). The version query changes when Vite re-bundles, but the browser may hold the old version if you bypass normal cache invalidation (e.g., manual node_modules edits).
development
Use when integrating Vite with a backend framework, rendering Vite assets from server-side templates, or setting up dev/production HTML serving. Prevents incorrect manifest.json traversal and missing CSS chunk resolution in production. Covers build.manifest configuration, .vite/manifest.json structure, ManifestChunk properties, dev mode HTML setup, production rendering, CSS/JS chunk resolution, and modulepreload polyfill. Keywords: backend integration, manifest.json, ManifestChunk, Django, Laravel, Rails, modulepreload.
development
Use when encountering dev server startup failures, HMR issues, proxy errors, CORS blocks, or module not found errors during development. Prevents misconfiguring server.hmr behind reverse proxies and forgetting appType: 'custom' in middleware mode. Covers HMR full-reload debugging, proxy configuration, CORS setup, HTTPS certificates, server.fs.strict violations, port conflicts, WebSocket failures, file watcher issues, and middleware mode. Keywords: dev server, HMR, proxy, CORS, HTTPS, WebSocket, port conflict, server.fs.strict, middleware mode, file watcher.
development
Use when encountering Vite build failures, chunk size warnings, or version-specific build errors. Prevents the common mistake of using deprecated rollupOptions in v8 or misconfiguring build targets and minifiers. Covers Rolldown/Rollup bundling failures, CSS minification errors, sourcemap problems, library mode build failures, BundleError handling, and asset processing errors. Keywords: build error, Rolldown, chunk size, sourcemap, library mode, minify, BundleError, rollupOptions, build.target.
tools
Use when configuring SSR environments, edge workers, custom environments, or migrating to the Vite 6+ environment model. Prevents using the Environment API on Vite 5 (where it does not exist) and misconfiguring per-environment vs shared plugin scoping. Covers per-environment build and dev settings, EnvironmentOptions interface, custom environment providers, shared vs per-environment plugins, configuration inheritance, and migration from Vite 5 implicit environments. Keywords: vite, environment api, vite 6, SSR, edge workers, per-environment config, providers.