esbuild Pre-Bundling vs Rollup Build: Keeping Vite Dev and Production Aligned
0 reputation · 03 Jan 2025, 19:41 UTC
Vite deliberately runs two pipelines: in dev, dependencies are pre-bundled to ESM by esbuild and cached under node_modules/.vite, while production builds go through Rollup. This split is documented architecture, not an accident, and it creates a real interoperability question for teams shipping packages that mix CommonJS and ESM entry points.
The constraint is that the two engines handle CJS interop, module resolution edge cases, and plugin ordering independently. Vite exposes optimizeDeps (include/exclude, esbuildOptions) for the dev side and build.commonjsOptions plus build.rollupOptions for the build side, but nothing in the config guarantees identical module graphs. A dependency can resolve one way under vite dev and another after vite build and preview.
The open decision is strategy: standardize on ESM-only dependencies to shrink the divergence surface, or accept mixed packages and tune both config surfaces continuously. Defaults also vary across recent major versions (Vite 5 and 6 at minimum), so any answer should be checked against the docs for the pinned release.
Specifically: which documented option pairing is intended to keep CJS interop consistent between the esbuild and Rollup paths? Is an ESM-only dependency policy the supported route to parity, or does Vite commit to supporting mixed CJS/ESM packages identically in both pipelines?