Speeding Up Vite Dev Server with Dependency Pre‑bundling
Learn how Vite’s esbuild‑based dependency pre‑bundling reduces browser requests, speeds up dev server start, and improves HMR—plus how to tune it safely.
07 Nov 2025, 02:01 UTC

Problem: slow startup and laggy hot updates
When a Vite project pulls in dozens of npm packages, the development server must transform each dependency on‑the‑fly. The browser ends up making dozens of requests for individual CommonJS modules, which can noticeably delay the initial page load and make Hot Module Replacement (HMR) feel sluggish.
Thesis: Vite’s built‑in esbuild pre‑bundling reduces request count and converts dependencies to native ES modules, giving a faster dev server and quicker HMR.
How pre‑bundling works
Vite runs esbuild over the dependencies listed in optimizeDeps. esbuild:
- bundles many packages into a few ES modules,
- transpiles CommonJS to ESM so the browser can load them natively, and
- removes duplicate code that appears when multiple packages rely on the same sub‑dependency.
The result is a set of files stored under node_modules/.vite that the dev server serves as static ES modules. Because the browser now receives far fewer requests, the initial load is quicker and HMR updates need to reload less code.
Configuring the feature
The pre‑bundler is on by default. To adjust which packages are processed, edit vite.config.js:
import { defineConfig } from 'vite'
export default defineConfig({
optimizeDeps: {
// packages to force into the pre‑bundle
include: ['lodash-es'],
// packages to keep out of the pre‑bundle (rarely needed)
// exclude: ['some-native-addon'],
// treat a package as ES module even if it ships CJS
// esbuildOptions: { target: 'es2020' }
}
})
Changes to optimizeDeps trigger a fresh bundle the next time the server starts, which can add a short pause if you switch the list often.
Worked example: pre‑bundling a large utility library
Suppose a React app uses lodash-es for many helper functions. Without tweaking, Vite treats each lodash sub‑module as a separate request. Adding it to include forces esbuild to bundle the whole library into a single ES module.
- Add the snippet above to
vite.config.js. - Restart the dev server (
npm run devorvite). - Open Chrome DevTools → Network, disable cache, and reload the page.
- Observe that the number of requests for
lodash-esdrops from dozens to one, and the transferred size is roughly the same but delivered in a single round‑trip. - Make a change to a component that imports lodash; notice that the HMR update finishes faster because fewer modules need to be invalidated and re‑loaded.
Trade‑offs and limitations
Pre‑bundling relies on esbuild’s ability to resolve dependencies. If a package:
- uses Node‑only APIs (e.g.,
fs,path), - has conditional exports that depend on the
browserfield in ways esbuild cannot simulate, or - contains native addons that require compilation,
- add the problematic package to
excludeso Vite leaves it unbundled and relies on its native CJS handling, or - provide a custom plugin that rewrites the problematic imports before esbuild sees them.
- Run
vitein a fresh terminal window. - Open the Network tab, enable “Disable cache”, and reload the app.
- Note the total number of requests and the waterfall time for the initial load.
- Stop the server, adjust
optimizeDeps.include(add or remove a package), and restart. - Repeat the reload and compare the request count and load time.
- Optionally, inspect
node_modules/.viteto see the generated ES module files for the packages you included.
the pre‑bundle may fail or produce runtime errors. In those cases you can:
Additionally, because the bundle is regenerated whenever the optimizeDeps list changes, frequently toggling inclusions can introduce a noticeable restart delay. Keep the list stable during a development session to avoid repeated rebundling.
Verification steps
To confirm that your configuration is having the intended effect:
If the request count drops and the page feels more responsive, the pre‑bundler is working as expected.
Closing: make it part of your baseline config
For most frontend projects, leaving optimizeDeps at its defaults already yields a noticeable speed‑up. When you identify a large library that is imported across many modules, explicitly adding it to include can shave off extra round‑trips and make HMR feel instantaneous. Keep an eye on packages that touch Node‑specific APIs; exclude them if you see errors, and you’ll retain the fast‑dev experience without surprises.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.