Force Vite to Pre-bundle Stubborn CommonJS Dependencies
Use vite.config.ts optimizeDeps.include to force pre-bundling of CommonJS packages and fix missing exports in Vite dev.
03 Nov 2025, 07:13 UTC

Vite Dev Server Cannot Find a CommonJS Export
You import a third-party library in a Vite project and the browser console shows "require is not defined" or a missing named export. The page works in production but fails in `vite dev`. The useful takeaway is to treat `optimizeDeps` as an explicit dev-time contract: tell Vite which dependencies to pre-bundle, then verify the generated files under `node_modules/.vite/deps`.
What Vite Does During Dependency Pre-bundling
Vite’s development server pre-bundles dependencies using esbuild before serving them. CommonJS (CJS) is a module format that uses `require` and `module.exports`, while browsers expect native ECMAScript Modules (ESM) with `import` and `export`. Vite converts CJS and UMD packages into ESM and writes the results to `node_modules/.vite/deps`, so the browser receives valid ESM URLs instead of raw Node-style files.
By default, Vite discovers dependencies by crawling your HTML entry points and static imports. Packages reached only through dynamic `import()` calls, lazy routes, or deeply nested conditionals can be missed until the first request triggers optimization, which causes inconsistent cold starts.
Force a Dependency with optimizeDeps.include
When automatic discovery misses a CJS package, `optimizeDeps.include` forces Vite to pre-bundle it. This is safer than excluding packages because it keeps Vite’s CJS-to-ESM transform active.
Worked Example: Include a Legacy Widget
Assume a package named `legacy-widget` distributes CommonJS code and throws interop errors in the dev server. In `vite.config.ts` at the project root:
import { defineConfig } from 'vite';
export default defineConfig({
optimizeDeps: {
include: ['legacy-widget'],
},
});Run this command in the project root to clear the stale optimizer cache:
vite optimize --forceThen restart the dev server:
viteNo special file permissions are required beyond normal read/write access to `node_modules`. The command rewrites the dependency cache under `node_modules/.vite`; the risk is that the next dev start re-runs pre-bundling, so the first start after the change may take a few seconds longer.
Open the browser’s Network tab and reload the page. Look for a request to:
/node_modules/.vite/deps/legacy-widget.jsIf that URL appears, Vite pre-bundled the package. If the browser still requests the raw package source or reports `require is not defined`, the package may not have been included correctly, or another dependency may be pulling it in outside the optimizer.
Limitations and Trade-offs
- `optimizeDeps` only affects the Vite development server. The production build uses Rollup, so a dev-time fix does not repair a production CommonJS interop problem.
- Pre-bundling adds disk usage and a one-time optimization cost on the first start or after `vite optimize --force`.
- Use `optimizeDeps.exclude` sparingly. Excluding a package skips Vite’s transform and can reintroduce `require is not defined` or missing-export errors in the browser.
Verify the Result
- Run `vite --version` and confirm the option names match your installed Vite version; `optimizeDeps` behavior can change between major versions.
- Run `vite optimize --force`, start `vite dev`, and inspect the Network tab for `/node_modules/.vite/deps/`.
- Run `vite build` and `vite preview` to confirm the same import works outside the dev optimizer. If it fails in preview, the issue is in the Rollup production pipeline, not `optimizeDeps`.
If the dependency still misbehaves, delete `node_modules/.vite` manually and restart the dev server. That forces a clean pre-bundle pass and usually clears stale cache entries.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.