Lesson 30 of 81
The bundler is the thing standing between saving a file and seeing the change — and starting with Next.js 16, the one doing that job by default isn't webpack anymore.
10 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A Next.js 16 project has a custom `webpack()` function in next.config.ts left over from an earlier version, and no one has touched the build config since upgrading. Someone runs `next build`. What happens?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Turbopack is Next.js's Rust-based bundler, and as of Next.js 16 it's stable and used by default for both next dev and next build. Previously it needed an explicit --turbopack flag; now the flags run in the opposite direction — --webpack opts out of it, back to the older JavaScript-based bundler Next.js has used since the beginning.
Why the rewrite matters isn't just "faster" as a vague claim — it's specifically about two things developers feel directly: dev server startup time and Hot Module Reload (HMR) speed, the delay between saving a file and seeing the change reflected. Webpack processes and bundles more of your app upfront; Turbopack's Rust engine does incremental, function-level compilation, so it can do meaningfully less work per keystroke-to-browser round trip, especially as a codebase grows.
Turbopack isn't a drop-in webpack replacement in every respect — it reimplements a webpack-compatible loader API (so many existing webpack loaders work unmodified) rather than running webpack's actual loader runtime, and its configuration lives under a dedicated turbopack key in next.config.ts, not inside webpack().
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
turbopack: {
resolveAlias: {
underscore: 'lodash',
},
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
}
export default nextConfig
This repo's own next.config.ts is currently an empty object, which is the common case — Turbopack works with zero configuration for the vast majority of apps, and you only reach for the turbopack key when you need a resolve alias, a custom loader rule, or a non-default project root.
next dev and next build — a candidate describing it as "the experimental bundler you turn on with a flag" is describing Next.js 15 and earlier, not the current version.--turbopack (or --turbo) now just force-enables what's already default; --webpack is the flag that actually changes behavior, opting back into the older bundler.experimental. It was experimental.turbo, then experimental.turbopack; in v16 it's a stable top-level turbopack key in next.config.ts — old configs under experimental need a codemod or manual migration.webpack() config doesn't get quietly skipped during a Turbopack build — it fails the build. This is deliberate: Next.js would rather force an explicit choice than silently apply only some of your configuration.this.importModule, this.emitFile, and full this.fs support aren't implemented — a loader that depends on those specifically won't work even though "Turbopack supports webpack loaders" is broadly true."What bundler does next dev use by default, and why would switching away from it ever be the right call?" tests whether a candidate's mental model of Next.js's build tooling is current — this is one of the more visible, easy-to-verify version-specific facts, and getting it backwards (assuming webpack is still default, or that Turbopack is still experimental) is a quick signal of stale knowledge.