Next.js 16의 Turbopack은 2.5배 더 빠르지만, 번들러는 빌드 과정에서 단 4%만 차지합니다.

작성자

카테고리:

← 피드로
DEV Community · Remdore · 2026-09-11 개발(SW)

Remdore

Remdore

Posted on Sep 11 AI-assisted

Next.js 16 makes Turbopack the default bundler and puts a number on it: builds 2 to 5 times faster than webpack. I wanted to know whether that holds on something bigger than the starter template, and where the time actually goes, so I built a 60-route app and timed every phase of the build with both bundlers.

The headline is true. It is also the least interesting thing I found. The claim describes the bundler, and on a warm build the bundler is about 4% of your build time. The rest is spent in places Turbopack does not touch, and one of them is a six-second phase with no progress bar that nobody talks about.

The app

Not a hello-world. Sixty route pages, each pulling in shared components: a Recharts line chart, a Markdown renderer, a client-side toolbar with lucide-react icons, date-fns, and a zod schema. About 2,000 lines across pages and components, on Next.js 16.3.4 and React 19.2. It builds cleanly and identically on both bundlers, which is the point: same input, swap only --turbopack for --webpack.

Every number below is a median of three runs, on the same machine, back to back.

Cold builds: the claim holds, at the low end

A cold build is no .next directory at all, the state your CI runs in unless you cache between jobs.

Turbopack webpack ratio Compile step 2.9s 7.2s 2.5x Total build (wall) 7.1s 18.8s 2.6x

So 2.5x on a cold compile. That is real, it is repeatable, and it sits at the bottom of the advertised 2-to-5x range rather than the top. If you were promised 5x on your CI and you do not cache anything between runs, you will feel closer to 2.5.

Warm builds: the cache is the real story

A warm build keeps .next/cache from a previous run and rebuilds the rest. This is what your laptop does all day, and what CI does if you cache the directory.

Turbopack webpack ratio Compile step 143ms 2.75s 19x Total build (wall) 3.45s 14.0s 4.1x

The compile ratio jumps to nineteen. Turbopack’s persistent cache takes the bundling step from three seconds to under a sixth of one. This is the number worth caring about, because it is the one you hit dozens of times a day, and it is well outside the range on the tin.

But look at the two rows. The compile got 19x faster and the total build only got 4x faster. That gap is the whole point of this post.

The bundler is 4% of your build

On the warm Turbopack build, the compile is 143 milliseconds out of a 3.45 second build. Here is where the rest goes:

Phase Turbopack warm Does the bundler own it? Compile 143ms yes TypeScript check 950ms no Static generation (64 pages) 380ms no Page data, finalizing, process startup ~2s no

Turbopack made the one part it controls almost free, and the build is still three and a half seconds because type checking, static generation and Next’s own orchestration do not get faster. Make the bundler infinitely fast and this build still takes over three seconds.

This is the honest reading of “2-5x faster builds”. The bundler is 2.5x to 19x faster depending on cache state, but the total build time you actually wait for improves less, and improves less the more pages you have to statically generate. On this app it was 4x warm. On an app with 600 pages instead of 60, the static generation phase grows and the bundler’s share shrinks further.

The six seconds nobody mentions

The strangest result was in webpack’s total, which did not add up from its phases. Compile 2.8s, TypeScript 1s, static generation 0.4s: that is about four seconds accounted for, out of a fourteen second build. I timestamped every line to find the missing ten.

Most of it is one phase: Collecting build traces, 6.6 seconds, with no progress bar and no mention in any benchmark I have seen.

[  4.1s] ✓ Compiled successfully in 2.7s
[  5.2s]   Finished TypeScript in 1069ms
[  6.8s] ✓ Generating static pages (64/64) in 429ms
[  7.3s]   Collecting build traces ...
[ 13.9s] Route (app)          <- 6.6 seconds later

Enter fullscreen mode Exit fullscreen mode

Build traces are the file-dependency graph Next computes so a deployment knows which files each route needs. On webpack it cost 6.6 seconds on this app. Turbopack emits no such phase at all: I grepped its entire output and there is no “Collecting build traces” line. Whatever it does instead is folded in and invisible.

So half of webpack’s warm build is a single phase that has nothing to do with compiling your code, and switching to Turbopack removes it. That is a bigger share of the win than the compile speedup, and no one advertises it.

Two more things worth knowing

The cache is bundler-specific. The first time I measured a warm Turbopack build, the compile came back at 3.1 seconds instead of 143 milliseconds. The cause was that the previous build had been webpack, and its cache does not carry over. Turbopack rebuilt from cold while believing it was warm. If you switch bundlers, or bounce between them in CI, your first build pays the full cold cost and there is no warning that it has.

The output is half the size. Turbopack’s .next came out at 81 MB against webpack’s 168 MB for the same app. I did not go chasing why, but if you cache the build output between CI runs, that is half the bytes to store and move.

What I got wrong on the way

I contaminated my own cache measurement and nearly reported the wrong number. My benchmark cleared everything in .next except the cache directory between runs, which is correct, but I ran Turbopack immediately after a webpack build and got a “warm” compile of 3.1 seconds. I almost wrote that Turbopack’s persistent cache barely helped.

The cache is per-bundler. My reset was fine; my ordering was not. Once I primed each bundler against its own cache before timing it, the real 143 millisecond warm compile appeared. The lesson is the same one as always: when a result looks flat, suspect the harness before the thing you are measuring. A warm build that is secretly cold looks exactly like a cache that does not work.

Run it yourself

Scaffold an app, then the comparison is two flags:

npx create-next-app@latest app --ts --app
cd app
rm -rf .next && time npx next build --webpack     # old default
rm -rf .next && time npx next build --turbopack   # new default

Enter fullscreen mode Exit fullscreen mode

To see the phase breakdown that matters, timestamp each line and watch for the build-traces gap:

rm -rf .next
start=$(date +%s.%N)
npx next build --webpack 2>&1 | while IFS= read -r l; do
  printf '[%5.1fs] %s\n' "$(echo "$(date +%s.%N) - $start" | bc)" "$l"
done

Enter fullscreen mode Exit fullscreen mode

The difference is small on a starter template and grows with your route count, so measure your own app, not a fresh one. I ran mine on an ordinary Linux laptop with Node 24.

What to do about it

If you are on Next.js 16 the default already gives you this, so there is nothing to switch on. The thing to change is what you expect and what you cache. Cache .next/cache in CI, because the warm compile is where the real speedup lives and a cold build throws it away. Do not expect the total build time to fall as far as the bundler benchmark suggests, because on a warm build most of your time is type checking and static generation, and those are exactly as slow as they were. And if your CI ever runs both bundlers, give them separate caches or the fallback to cold will be silent.

The 2-to-5x number is not wrong. It is just answering a smaller question than the one you have, which is how long you wait for the whole build. On this app that answer was 4x, most of it from a phase the benchmarks do not name.

원문에서 계속 ↗