The frontend build pipeline has evolved dramatically. webpack dominated for years; modern tools (Vite, esbuild, Turbopack) are dramatically faster and simpler. The shift is real and ongoing.
This page covers the modern landscape and how to think about it.
A bundler takes your source code (JS, TS, CSS, etc.) and produces optimized output for the browser:
Older tools (webpack) did all of this in JavaScript. Newer tools use Go, Rust, or Zig — much faster.
The legacy default. Configurable to do anything. Slow on big projects.
Pros: mature; massive ecosystem; handles edge cases. Cons: slow; complex config; legacy patterns.
For new projects, rarely the right choice. For migrating off webpack, see below.
The modern default. Uses esbuild (Go) for dev; Rollup for production. Dev server starts instantly; HMR is fast.
Pros: very fast; excellent DX; sane defaults. Cons: Rollup-based plugins differ from webpack; some legacy projects struggle to migrate.
For new React, Vue, Svelte projects, Vite is the standard.
A bundler written in Go. Extremely fast. Used by Vite, Tailwind, and others as a building block.
Pros: very fast. Cons: limited compared to bundlers using it as a library.
Use directly for tooling, lambda bundling, etc.
Vercel's bundler in Rust. Designed to replace webpack for Next.js. Newer; less mature than Vite but evolving fast.
Used in Next.js 13+ and beyond.
Older modern bundler. Zero-config. Less popular than Vite.
Library bundler (output libraries, not apps). Used by Vite for production builds. Excellent at clean ESM output.
Not a bundler; a transpiler. For pure TS projects, sometimes the build pipeline is just tsc. Slow compared to esbuild/swc for transpilation but produces full TS errors.
Old webpack on a big project: 30-60 second startup; multi-second HMR. Vite: instant startup; sub-second HMR.
For developers, this is transformative. Tighter feedback loop; less waiting.
Modern tools have fewer config knobs because they make better defaults. Vite's config is often a few lines.
Modern bundlers prioritize ESM (ECMAScript Modules) — the standard module system. Native ESM in browsers and Node.
For most projects, plan a migration to Vite or stay on Next.js (which now uses Turbopack).
For most React/Vue projects, the migration is straightforward:
index.html as entry)For complex webpack configs, more work. Start with a small slice; verify; expand.
Some old SPA projects benefit from migrating to Next.js (which handles bundling, SSR, routing). Larger migration but ends up with more capability.
Smaller is better. Tools to analyze:
vite-bundle-visualizer (Vite)webpack-bundle-analyzer (webpack)npm run build -- --stats (varies by tool)Common bloat:
Don't ship all JS at once. Split by route:
const Lazy = React.lazy(() => import('./LazyComponent'));
Bundlers handle the chunk creation; runtime loads lazily.
Production source maps for debugging. Hide from users (private, on internal server) but generate them.
// Vite uses import.meta.env
const apiUrl = import.meta.env.VITE_API_URL;
Different tools have different conventions for what's available at build time vs. runtime.
For projects with build performance issues:
--profile or equivalent.For very large monorepos, Turborepo or Nx provides cross-project build caching.