skip to content

Your team wants to move a large Next.js app's production builds from webpack to Turbopack. How would you validate that switch before you ship on it?

level: seniorimportance: should knowfreq 34%

answer

  1. audit the bundler-specific surface first
  2. plugins are the likely blocker
  3. build both ways, diff the artifacts
  4. source maps fail quietly
  5. keep --webpack as the documented exit

basics

~20 s

Build the same commit with both bundlers and compare: does every route compile, are the emitted routes and their sizes equivalent, do source maps still reach your error tracker, and does the built app behave the same under smoke tests. Ship behind the ability to fall back to webpack, then watch build times and runtime errors.

solid answer

~50 s

Treat it as a toolchain migration with a rollback lever, not a flag flip. First audit `next.config` and the toolchain for bundler-specific surface: a custom `webpack()` function, webpack plugins — which have no Turbopack equivalent — non-standard loaders, and any tool that hooks the build to upload source maps. Then build the same commit both ways and diff the outputs: every route present, bundle sizes in the same neighbourhood, CSS pipeline intact, source maps generated and consumable. Because dev only ever compiled the routes people opened, the build is the first thing that exercises every route, so expect it to surface latent errors that are not Turbopack's fault. Run the built app against your smoke or end-to-end suite rather than trusting size diffs alone, and in a monorepo confirm the workspace root Turbopack infers is the one you intend. Ship it in CI first, keep `--webpack` as the documented fallback, and watch build duration and client error rates for a release before deleting the old path.

go deeper

for a junior

Know that changing bundlers changes how the production output is produced, so the same commit should be built both ways and compared rather than trusted because the dev server was happy.

for a middle

Be able to list what to compare — route coverage, per-route bundle sizes, CSS output, source maps — and to explain that a custom webpack config and any webpack plugins must be ported or replaced first.

for a senior

An interviewer wants the operational plan: audit, dual build, diff artifacts, smoke-test the built app, roll out in CI with --webpack as a documented rollback, and watch build time and client errors before deleting the old path.

for a principal

Own the decision framing — what the faster builds are worth against migration and dual-maintenance cost, who is accountable for the rollback window, and the standing rule that the org does not run two bundler pipelines indefinitely.

## Why this is a migration and not a flag Bundling is the step between your source and everything users execute. A different bundler resolves modules, splits chunks, orders CSS and emits source maps by its own rules. The output is *supposed* to be equivalent, and in a plain App Router app it is — but the surface where it might not be is exactly the surface teams have customized. So the validation plan is: find the customization, prove equivalence where it matters, keep an exit. ## Step one: audit the bundler-specific surface Before building anything, read `next.config` and the toolchain with one question in mind — what here talks to webpack? - A **`webpack()` function**. Turbopack never reads it. Every rule inside is a port to `turbopack.rules` or a deletion because Turbopack already handles it natively (CSS, CSS Modules, PostCSS, Sass). - **webpack plugins**. There is no plugin API in Turbopack, so these cannot be ported by configuration. This is the item most likely to block the whole migration, which is why it belongs at the top of the audit rather than in the middle of a failing build. - **Loaders that reach into webpack internals.** The loader subset Turbopack supports covers the common cases; a loader manipulating compilation objects does not survive. - **Anything that hooks the build for observability** — source-map upload to an error tracker being the classic case, because it is usually implemented as a plugin and because it fails quietly: the build is green, and three weeks later nobody can read a stack trace. ## Step two: build both ways on the same commit Run the production build with each bundler and compare artifacts rather than impressions: - **Route coverage.** Every route that built before builds now. Errors here are frequently *not* Turbopack's fault — dev compiled only the routes people opened, so a build is the first pass that touches everything. - **Output size.** Per-route JavaScript and CSS in the same neighbourhood. A large unexplained swing means a chunking or resolution difference worth understanding before shipping, not after. - **Styling.** CSS and CSS Modules emitted, and — the subtle one — cascade order preserved, since ordering bugs look like random visual regressions. - **Source maps.** Generated, uploaded if that is part of your pipeline, and actually resolving a symbol you can check by hand. ## Step three: exercise the built app Size diffs do not catch a component that renders differently because an asset import changed shape. Start the built application and run whatever smoke or end-to-end coverage you have against it, then walk the surfaces most sensitive to bundling by hand: routes with dynamic imports, anything importing SVGs or other non-JS assets, pages with heavy third-party libraries, and any code branching on environment variables. In a monorepo, confirm the workspace root Turbopack infers is the one you intend — a wrong root changes what is in scope for resolution and produces confusing misses. ## Step four: roll it out with an exit ```bash next build # Turbopack (default in Next 16) next build --webpack # documented fallback while the migration settles ``` Flip CI first, on a branch, and let it run for a while before it becomes how you ship. Keep `--webpack` documented as the rollback and make sure someone other than the migrator knows about it. Then watch two signals for at least a release: **build duration** in CI, which is the payoff you are buying, and **client-side error rate**, which is where a subtle bundling difference shows up. Delete the webpack configuration only after that window closes cleanly — and note the deletion is itself the point, since carrying two configured pipelines indefinitely is the expensive outcome. ## What good judgment sounds like here The weak answer is "we flipped the flag and the build was faster." The strong answer names the equivalence checks, admits that build-only failures are usually pre-existing bugs the demand-driven dev server never surfaced, and keeps a rollback until real traffic has validated the artifacts.

  • The Turbopack build fails on a route that the dev server never complained about. Is that a Turbopack bug?
    Usually not. The dev server is demand-driven and only ever compiled the routes someone opened, so a production build is the first pass that touches every route. Read the actual error before blaming the bundler: a broken import or a missing loader in a rarely-visited route is a latent bug the build has finally exposed. Reproduce it by building with webpack too — if both fail, it was never Turbopack.
  • Which failure from a bundler switch is most likely to ship unnoticed?
    Broken source maps. The build stays green, the app works, and nothing signals a problem until an incident when every stack trace in the error tracker is minified noise. Source-map generation and upload are often wired through webpack plugins, which have no Turbopack equivalent, so verify end to end — trigger a real error in a staging build and confirm the tracker resolves it to a source line.
  • What would you monitor after the switch becomes how you ship?
    Build duration in CI, since that is the benefit you bought and a regression means the migration is not paying for itself; client-side error rate and volume, where a subtle chunking or resolution difference surfaces; and per-route bundle sizes over the next few builds. Give it a full release before deleting the webpack configuration, and keep the fallback documented until then.

saying these in an interview costs you the question

  • Flips the default in CI and calls the migration done once the build is green
  • Compares only build time and never compares output
  • Assumes dev running clean means every route builds
  • Forgets source-map generation and upload entirely
  • Deletes the webpack config on day one, leaving no rollback

context