On this page · sections
Vite vs Webpack
Vite’s native ESM dev server vs webpack’s bundle-first dev graph is a standard senior loop question. Interviewers want architectural trade-offs, not “Vite is faster because Go.”
| Layer | Vite | Webpack |
|---|---|---|
| Dev server | Native ESM + on-demand transform | In-memory bundle of full graph |
| Prod build | Rollup bundle + shake | Chunk graph + splitChunks |
| Strength | Fast default SPA DX | Federation, custom loaders, enterprise graphs |
| Dep handling | esbuild optimizeDeps pre-bundle | Full graph compile |
Dev Server Architecture
Definition
Webpack dev builds a dependency graph into an in-memory bundle before serving — cold start and rebuild cost grow with app size.
Vite dev serves source as native ESM: the browser requests each module, Vite transforms only the requested file on the fly (TS, JSX, CSS), and uses esbuild for dep pre-bundling.
// vite.config.js (conceptual)
// export default {
// server: { port: 5173 },
// optimizeDeps: { include: ['react', 'react-dom'] },
// };
// Browser requests:
// GET /src/main.jsx → Vite transforms JSX → ESM
// GET /node_modules/.vite/deps/react.js → pre-bundled depVite dev: Browser requests /src/App.jsx → transform single file → return ESM
Webpack dev: Entry main.jsx → build full module graph → serve from memory bundleoptimizeDeps pre-bundles CJS/UMD deps to ESM with esbuild on first dev start — avoids hundreds of nested requests. Force re-run with --force after dep changes.
Vite transforms with esbuild/swc — not full Rollup in dev.
Interview: Vite dev cold start is roughly O(deps pre-bundle), not O(app modules).
Production Build Pipelines
Definition
Vite production runs Rollup — strong ESM tree-shaking, code splitting, and lean output. Plugins are mostly Rollup-compatible.
Webpack production is a mature chunk graph engine with Module Federation, granular loader chains, and deep customization.
// vite.config.js — production split
// export default {
// build: {
// rollupOptions: {
// output: {
// manualChunks: { vendor: ['react', 'react-dom'] },
// },
// },
// minify: 'esbuild',
// },
// };
// webpack.config.js
// optimization: {
// splitChunks: {
// chunks: 'all',
// cacheGroups: { vendor: { test: /node_modules/, name: 'vendors' } },
// },
// },Compare fairly: Vite prod is Rollup — saying “Vite uses esbuild in production” is incomplete unless you mean minification only.
esbuild minify — faster builds, sometimes slightly larger output. terser — slower, finer dead-code patterns. Benchmark gzip on your app.
Interview: Vite prod is Rollup, not esbuild bundling — different code path from dev.
When to Choose Webpack
Definition
Choose webpack when you need Module Federation at scale, deeply custom loader chains (legacy templating, proprietary formats), or plugins with no Rollup equivalent.
// webpack Module Federation — host loads remote at runtime
// new ModuleFederationPlugin({
// name: 'host',
// remotes: {
// checkout: 'checkout@https://cdn.example.com/remoteEntry.js',
// },
// shared: { react: { singleton: true, requiredVersion: '^18.0.0' } },
// });Need Federation + custom loaders + years of webpack config?
→ Stay webpack or migrate slice-by-slice
Greenfield SPA with no Federation lock-in?
→ Vite defaultRspack — webpack-compatible API with Rust speed as migration path. @originjs/vite-plugin-federation exists for Vite — evaluate maturity against webpack’s battle-tested plugin.
Enterprises with years of webpack config — Federation remotes, DLL references, custom splitChunks for 50 entries — often migrate incrementally.
Interview: Module Federation depth and sunk config cost keep teams on webpack — not ideology.
HMR & Cold Start
Definition
Cold start: Vite serves index HTML immediately and compiles modules on first request. Webpack must compile the reachable graph before first useful response.
HMR: Vite invalidates an ESM boundary — often sub-100ms for a leaf component. Webpack HMR walks the module graph via module.hot.accept — mis-accepted boundaries force full reload.
'use client';
import { useState } from 'react';
export function HotDemo() {
const [n, setN] = useState(0);
return (
<button type="button" onClick={() => setN((v) => v + 1)}>
{n}
</button>
);
}
// Edit JSX — state preserved if export is React componentVite HMR uses import.meta.hot. Webpack uses module.hot.accept. Both support React Fast Refresh with correct plugins.
Webpack cache: { type: 'filesystem' } cuts rebuild time. Vite pre-bundle cache lives in .vite/deps.
Full page reload triggers: HTML entry changes, env file changes, optimizeDeps rebuild, plugins that cannot HMR.
Interview: HMR update latency is O(affected subtree) — Vite’s ESM boundaries often yield smaller subtrees for leaf edits.
Migration Strategy
Definition
Migrate incrementally or vertical slice: start with a greenfield package on Vite, then port apps.
Breakage categories:
require()/ CommonJS in sourceprocess.envvsimport.meta.env- SVG/asset imports needing
?urlor plugins - Jest mocking
import.meta - Custom webpack loaders without Rollup equivalents
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
return {
define: {
'process.env.NODE_ENV': JSON.stringify(mode),
'process.env.LEGACY_API': JSON.stringify(env.LEGACY_API),
},
resolve: { alias: { '@': '/src' } },
};
});Staff approach: ADR with rollback plan — keep webpack CI job for one release train. Measure build time, bundle size, and DX survey — not only startup anecdotes.
Monorepo: per-package tooling via Nx/Turborepo during transition. vite-plugin-legacy for older browser targets.
Interview: Top breakage categories are env variables and asset imports — not “just swap config.”
Senior Interview Summary
Dev architecture
Vite = unbundled ESM + on-demand transform. Webpack dev = bundled graph in memory.
Production
Vite prod = Rollup + shake. Webpack prod = chunk graph + splitChunks + Federation.
When webpack wins
Module Federation, custom loaders, sunk enterprise config, unified dev+prod graph model.
HMR
Vite
import.meta.hot· webpackmodule.hot.accept· both need correct Fast Refresh boundaries.
Migration
Incremental slices · env + asset breaks · ADR with rollback · keep Federation on webpack until strategy settled.
Best mental model
Dev speed → request-scoped transform vs full graph compile
Prod output → Rollup lean default vs webpack graph features
Decision → greenfield vs Federation lock-in vs migration costPractical rules
Greenfield SPA → Vite default
Federation at scale → webpack (or evaluate Rspack)
Dual tooling in monorepo → acceptable during transition
Prod validation → separate from dev parityWhat to say in interviews
Draw the line dev = ESM vs bundle and prod = Rollup vs webpack graph. Name Module Federation as the main webpack differentiator. For migration, list env vars and asset imports as top breakage categories — interviewers hear “zero config” too often.