Contents
In brief
Turbopack in Next.js does not ship your client JavaScript as one file. It emits many chunks—app code, dependencies, and the runtime that wires them together. The Next.js blog walks through why “one mega-bundle” and “one file per module” both fail at scale, and how merging inside chunk groups balances download size against request count. Next.js 16.3 adds experimental levers: smarter fetching against what the browser already has, analytics-shaped merge weights, CommonJS tree-shaking, and a shared runtime chunk.
What happened
The extremes are easy. One giant chunk caches well after the first hit, but every page pays for every other page’s JavaScript. One chunk per page stays slim, yet shared UI like <Footer /> is duplicated and re-downloaded on each route. One chunk per module never over-ships and caches finely—but hundreds of tiny requests still cost HTTP overhead, and compression works worse across many small files than inside one larger one.
Turbopack merges small chunks into larger ones, but only inside a chunk group: the set of chunks that always load together (for example everything for /home vs /blog). Merging inside a group cannot add code the page was not already going to download. Whether a merge pays off depends on the visit pattern: bounce after one page versus navigate further. Merging a site-wide chunk A with a home-only chunk B wins on a single visit; on a later page that needs only A, the browser may download A again because it was glued to unused B.
On nextjs.org, three modes were compared: never merge, Turbopack defaults, and one chunk per group. Defaults cut requests by more than half while shipping slightly less code overall; max merging cut requests further but shipped about 10% more JavaScript across a longer navigation session.
Why it matters
Chunking is not bundler trivia—it is the trade-off between first paint, cache reuse, and soft navigation cost. The build decides merges before anyone visits and cannot see the browser cache; the algorithm also guesses how many sessions are single-page (about two-thirds in the post). That is why “just fewer chunks” or “always split finer” without route context often backfires.
For teams on Next.js, the 16.3 flags close those blind spots: the runtime can pick the cheaper option—merged file or missing pieces—and config can encode real route clusters instead of a universal guess about bounce rate.
In practice
- Move to Next.js 16.3+ and read options under
experimental.turbopackChunkinginnext.config.jsinstead of copying someone else’s magic numbers. - Enable
generateComponentChunksso unmerged pieces ship alongside merged ones; at request time Turbopack picks whichever is cheaper given what is already loaded. - Feed your analytics:
firstPageLoadPriority(default0.67),priorityRoutesfor critical URLs, andclustersfor routes people visit together. - Ship less code:
experimental.turbopackCjsTreeShaking(CommonJS tree-shaking; ESM was the main path before) andexperimental.turbopackSharedRuntime—one shared runtime chunk instead of per-page runtimes (about 10 KB and one blocking request saved on later navigations). - Measure on your navigation paths: a high-bounce marketing site wants different merge pressure than a long-session dashboard.
Takeaway
Good JavaScript chunking is neither maximum nor minimum file count—it is a conscious compromise inside chunk groups, guided by how people actually move through the app. Experimental Turbopack options in Next.js 16.3 let the build meet the browser cache and your route map; turn them on deliberately and verify with measurements.

