Last updated: May 16, 2026

Vite ships two bundlers inside one tool — esbuild in dev, Rollup in production — and a plugin that hooks the wrong lifecycle will silently no-op in one of the phases. That’s the most honest objection to the recommendation that follows, and it still isn’t enough to flip the call: for a new React project, pick Vite, and only reach for Webpack if you can name a specific build-graph feature — Module Federation, a custom loader graph, or an existing federated monorepo — that you actually need. The “small project vs large project” framing every SERP article reaches for has been wrong for years. Project size never decided the bundler; build-graph requirements did.

Editorial illustration for The case against Webpack for greenfield React projects
Vite ships two bundlers inside one tool — esbuild in dev, Rollup in production — and a plugin that hooks the wrong lifecycle will silently no-op in one of the phases.

  • The React team deprecated Create React App on February 14, 2025 and recommended Vite, Parcel, or Rsbuild as build-tool replacements, ending CRA’s role as the default Webpack-on-React on-ramp.
  • Vite uses two bundlers internally: esbuild pre-bundles dependencies in dev and Rollup builds production. The Vite team has announced Rolldown as the path to unifying both; check the current Vite release notes for the status of that migration in your version.
  • Webpack’s dev-server slowness is architectural: it must crawl and resolve the whole module graph before serving a byte, whereas Vite serves native ESM URLs to the browser and transforms files on demand.
  • Module Federation is the single strongest remaining reason to start on Webpack today; community Vite plugins exist but, per their own repos, are not at full production parity for the harder micro-frontend cases.
  • Both ecosystems already have their successors mapped: Vite is migrating to Rolldown (Rollup-compatible) and Webpack to Rspack (Webpack 5-compatible).

The verdict in one line, and the three escape hatches

The default for a greenfield React app is Vite. Three things, and only three things, justify reaching for Webpack instead: you need Module Federation at production parity for a micro-frontend setup, you have a custom loader graph with bespoke transforms (binary assets, niche compilers, internal preprocessors) that has no Rollup-plugin equivalent, or you’re integrating into an existing federated monorepo whose host shell expects Webpack’s chunking conventions. Everything else — bundle size, tree-shaking quality, library support, TypeScript ergonomics, CSS handling — is now table stakes either way.

The SERP’s favorite framing, “Vite for small projects, Webpack for large ones,” is wrong on its own terms. Application size has never determined bundler choice; build-graph requirements have. A 200-component admin dashboard with no federation needs the same bundler as a 20-component marketing site. A 30-component shell that has to consume three remote bundles published by three other teams needs Webpack (or Rspack), regardless of its component count.

Terminal output for The case against Webpack for greenfield React projects
Captured output from running it locally.

Why ‘project size’ was always the wrong axis

Look at the actual decisions a bundler has to make for a React app: how to resolve import specifiers, how to transform JSX/TS, how to split chunks, how to fingerprint output, how to handle CSS/asset modules, how to expose modules to other apps at runtime. Of those, only the last one — runtime exposure across separate deployments — is something Webpack does and Vite still can’t fully match in the harder cases. Every other capability is feature-equivalent across the two ecosystems for normal app work.

The competitor SERP articles keep gesturing at “complex apps” and “wide variety of third-party libraries” without naming a single library Vite genuinely can’t handle. They can’t name one, because for app-level dependencies the difference disappeared two years ago. The Rollup-compatible plugin surface plus the unplugin shim layer covers the same ground for app concerns. What remains is the narrow, real list above.

A related write-up: runtime-level architectural wins.

The mechanism the SERP doesn’t explain: browser-as-module-loader

Webpack’s dev slowness isn’t a bug or a tuning problem. It’s the cost of the model. Webpack treats the browser as a dumb runtime that gets a finished bundle. So before serving the first request, Webpack has to crawl every import, resolve every bare specifier (react, lodash-es/debounce), compile every JSX file, and assemble a graph. Whether you’re starting with one component or a thousand, the bootup work scales with the graph.

Vite flips the model. Browsers ship a working native ESM loader: they will fetch and execute module URLs over HTTP — import x from "/src/App.js" works in any modern browser. What browsers do not do natively is understand TSX, JSX, or bare specifiers like react. Vite fills that gap on the server side. It transforms each TSX/JSX file on the fly when the browser requests it, rewriting bare specifiers to URLs the browser can fetch, and it pre-bundles npm dependencies (so the browser doesn’t fire 800 requests for lodash-es internals or choke on CommonJS-only packages). The browser never sees raw TSX; it sees the transformed JS, served as native ESM. The Why Vite page makes this explicit: startup time is roughly constant in application size because the dev server isn’t building the whole graph upfront — it’s transforming files lazily, on demand.

Background on this in Vite’s HMR dependency graph.

Topic diagram for The case against Webpack for greenfield React projects
Purpose-built diagram for this article — The case against Webpack for greenfield React projects.

The trade-off Vite boosters skip: two bundlers in one tool

Here is the warning a Vite-first article owes the reader. Vite has historically shipped with two bundlers: esbuild for dev-time dependency pre-bundling and Rollup for production builds. Rolldown is the announced successor that’s intended to unify both paths; whether the version of Vite you’re on uses it by default depends on which release you install, so check the current Vite changelog before you assume one engine. Until your project is on a Rolldown-unified Vite, the duality remains. The Vite docs on dependency pre-bundling describe why this is necessary — CommonJS-shipped deps have to be converted to ESM for the browser, and ESM deps with hundreds of internal modules get collapsed into a single fetch.

The footgun: a Vite plugin can behave differently in the two phases. Plugins that hook only Rollup lifecycle methods (renderChunk, generateBundle) do nothing during dev. Plugins that target esbuild’s transform API don’t run during production. Most app-level plugins (the React plugin, the Vue plugin, the Tailwind plugin) are written to handle both, but you will eventually hit a tool — usually a niche transformer, a polyfill plugin, or an internal monorepo plugin — that works in one and not the other. Webpack, for all its flaws, runs one engine in both modes.

the transpilation layer underneath goes into the specifics of this.

Official documentation for webpack vs vite new project
The primary source for this topic.

What actually changed in 2025

The SERP is stuck in 2024. Several things shifted that the top-ranking pages haven’t caught up to:

  • Create React App was deprecated. The React team’s Sunsetting Create React App post (February 14, 2025) cited “no active maintainers” and named Vite, Parcel, and Rsbuild as the build-tool replacements. CRA was the default Webpack-on-React on-ramp for almost a decade. That on-ramp is gone.
  • Rspack 1.0 shipped. The Rspack 1.0 announcement (August 2024) put a Rust-based, Webpack-API-compatible bundler into production status, with compatibility for a large share of the top Webpack plugins and Module Federation support.
  • Rolldown reached its 1.0 milestone. The Rolldown 1.0 announcement from VoidZero ships a Rollup-compatible, Rust-written bundler that the Vite team has positioned as the future single engine for Vite. The exact Vite version it becomes the default in is something to confirm against the current Vite release notes for the version you’re installing.

The framing in 2024 was “Vite is fast but Webpack has the ecosystem.” Today the framing is “Vite is fast and Webpack has Module Federation.” That is a much smaller carve-out.

There is a longer treatment in the broader Vite shift.

The migration-cost argument: every Webpack-first greenfield project is already on the clock

Start a new React project on Webpack 5 today and you are starting on a deprecation curve. Webpack’s own ecosystem — most visibly ByteDance’s web infra team behind Rspack — is moving the API forward in Rust. The Webpack 5 plugin surface is largely frozen. CRA is sunset. The React docs do not list Webpack as a build tool to start with for a new app. Tooling decisions you make today will have to be revisited inside the next two years, whether that means moving to Rspack (cheap, API-compatible) or to Vite (harder, but the destination most teams already pick).

Terminal animation: The case against Webpack for greenfield React projects
Watch the code run step by step.

The strongest counter-argument

The most honest objection to all of this: Webpack’s plugin and loader ecosystem still has long-tail coverage that Rollup-flavored ecosystems do not. If your build legitimately depends on a niche transformer published only as a Webpack loader — an internal asset pipeline, a custom DSL compiler, a corporate-mandated obfuscator — porting it to a Rollup plugin is real work. And if you’re running a micro-frontend architecture today, the Vite Module Federation plugins (originjs/vite-plugin-federation and the newer @module-federation/vite) exist but, per their own READMEs and open issues, are not at full production parity with Webpack’s implementation for the harder cases (shared singletons across remotes, eager loading, complex chunking).

Related: modern monorepo tooling.

The rebuttal: this is exactly why the article above carved out the three escape hatches. A team that has the loader graph or the federation requirement should pick Webpack — or, increasingly, Rspack, which keeps Webpack’s API and adds Rust speed. The argument isn’t “Vite is right for every team.” It’s “Vite is right by default, and the exceptions are nameable and narrow.” A team that can’t name its Webpack-only requirement isn’t disagreeing with the recommendation; it’s confessing it hasn’t done the analysis.

When Webpack is still the right call for a new React project

  • Native ESM dev serving: Vite yes; Webpack no (the full graph must be built before the first byte is served); Rspack no (it inherits Webpack’s bundle-first model, just faster in Rust).
  • Module Federation at production parity: Webpack yes; Rspack yes; Vite partial — the two community federation plugins’ own repos document gaps for shared singletons, eager loading, and complex chunking.
  • Custom loader graph for internal or legacy loaders: Webpack yes; Rspack yes (Webpack-compatible loader API); Vite no without a Rollup-plugin port.
  • TypeScript and JSX with no extra configuration: All three.
  • HMR cost on large apps: Vite roughly constant-time (lazy on-demand transforms); Rspack fast via Rust-based incremental rebuilds; Webpack scales with the module graph.
  • Active maintenance trajectory: Vite (migrating to Rolldown) and Rspack are both moving forward in Rust; Webpack 5’s plugin surface is largely frozen.
Decision rubric: when to start a new React project on Webpack
Requirement Pick Webpack/Rspack? Why
Production Module Federation with shared singletons across remotes Yes Vite plugins exist but their own repos document gaps for the harder federation cases.
Custom loader graph: internal binary compiler, mandated obfuscator, niche DSL Yes Loader was written for Webpack; no Rollup-plugin equivalent.
Integration into an existing federated monorepo using Webpack chunking Yes Host shell expects Webpack-shaped remotes; cross-bundler federation is fragile.
Large React SPA, TypeScript, Tailwind, no federation No — pick Vite App size does not determine bundler; build-graph features do.
Marketing site, dashboard, internal tool No — pick Vite or a framework on Vite (Remix, TanStack Start) Faster dev loop, less config, no Webpack-specific feature in use.
“We’ve always used Webpack” No — Rspack is the safe escape valve API-compatible, Rust-fast, supports Module Federation. Webpack 5 is not the destination.

How this was evaluated

The recommendation above is built from three sources of evidence: the official deprecation and release posts cited inline (React’s CRA sunset, Rspack 1.0, Rolldown 1.0), the architectural mechanism Vite’s own documentation describes (native-ESM dev serving, dependency pre-bundling), and the current status of the two Vite Module Federation plugin repos on GitHub. Version-specific claims — which Vite release defaults to Rolldown, the exact Module Federation feature matrix in the Vite plugins — move quickly, so re-check the corresponding release notes and READMEs against the version you’re installing.

Background on this in smaller React alternatives.

What this means if you’re not actually picking a bundler

Most teams starting a greenfield React app shouldn’t be picking a raw bundler at all. They should be picking a framework — Next.js (Turbopack), Remix, TanStack Start, Expo for native — and the bundler decision follows. If you’re far enough along that you’re hand-rolling a Vite or Webpack config from scratch, you’ve already opted into the bundler conversation. Otherwise the answer is: pick the framework whose runtime model matches your app, and let it pick the bundler.

The one concrete takeaway, then: if you find yourself comparing webpack vs vite new project for a fresh React codebase, default to Vite, name your Webpack escape hatch in writing if you have one, and pick Rspack over Webpack 5 if you do. Greenfield Webpack 5 is starting on a deprecation curve nobody is going to bend back upward.

More detail in Turbopack going production-ready.

References