Turbopack chunking is the part of a headless build nobody inspects until the storefront feels heavy on a mid-range Android in Jakarta. Vercel published the internals on September 3, and the measurements deserve a read before you commit a client to a React storefront. On its own site, the same code shipped 96 requests under one configuration and 15 under another, with roughly 48 KiB of difference in total JavaScript. That spread is a deliberate tradeoff, not a bug.
What Turbopack chunking changed in Next.js 16.3
Next.js 16.3 added experimental controls that let you tune how Turbopack merges JavaScript chunks, plus three features that ship less code in the first place. The write-up by Vercel's Sam Poder, produced during a summer internship on the Turbopack team, sets out the algorithm. Turbopack collects the chunks a page always loads together into a chunk group, then merges chunks inside a group when merging is likely to cut requests without over-shipping code to other pages.
That merge decision is a bet on how people move through your site. Turbopack assumes two thirds of sessions are a single page view and one third involve at least one navigation. The assumption is now a knob. In the turbopackChunking config, firstPageLoadPriority defaults to 0.67 and shifts weight toward a fast first paint as you raise it. Vercel suggests your bounce rate as a starting value. priorityRoutes marks the pages whose load speed matters most, and clusters describes sets of routes people tend to visit in one session, each written as an array of regular expressions.
Three further flags cut the payload itself. generateComponentChunks emits un-merged copies of chunks alongside the merged ones, so the runtime can fetch whichever is cheaper given what the browser already holds. turbopackCjsTreeShaking extends tree-shaking to CommonJS modules, which previously shipped their unused exports to the client. turbopackSharedRuntime replaces the per-page runtime with one shared chunk, saving a blocking request and about 10 KB of client JavaScript on every navigation after the first. Both tree-shaking and the shared runtime are slated to become defaults later.
Three chunking strategies, measured
Turbopack's defaults won overall on Vercel's own test, cutting requests by more than half against no merging while shipping slightly less code. Across an eight-step navigation through nextjs.org, never merging produced 561.6 KiB over 96 requests. The defaults produced 554.8 KiB over 38 requests. Merging everything within each chunk group produced 610.0 KiB over 15 requests, roughly 10 percent more JavaScript for the fewest round trips.
The ranking inverts if you only count the first page. On the initial load of nextjs.org, maximum merging was the lightest at 315.3 KiB in 6 requests, the defaults sat at 344.2 KiB in 24 requests, and no merging was heaviest at 363.6 KiB across 76 requests. Aggressive merging is excellent for a visitor who lands once and leaves, and expensive for one who browses, because a merged file is useless on the next page unless that page needs every piece of it.
That is the whole shape of the problem for commerce. Paid social traffic landing on a product page and bouncing is the merge-everything case. A customer moving from category to product to cart is the opposite case. Most stores run both at once, on different traffic sources, which is exactly why a single global default has always been a compromise.
Why Hyvä storefronts never see this decision
A Hyvä storefront has no chunk graph to tune, because Magento renders the HTML on the server and Hyvä layers Alpine.js and Tailwind on top rather than shipping a page-level JavaScript bundle. There is no build-time merge heuristic guessing at your funnel, because there is no bundler deciding what a page needs. The browser gets markup and a small amount of behaviour attached to it.
We say this without smugness, because it is a genuine tradeoff rather than a free win. Server-rendered Hyvä gives up the app-like transitions and client-held state that a React storefront makes easy. Turbopack chunking is the tax you accept in exchange for those. The useful question is not which stack is faster, since both can be fast. It is whether your store needs client-side state badly enough to take on a bundle-splitting problem that now has six configuration flags attached to it. For most catalogue-driven stores in our e-commerce work, the answer is no. For configurators, quote builders and anything with a genuinely stateful cart, it is yes, and that is where our headless commerce builds live.
What we would change this quarter
If you run a Next.js headless storefront on 16.3 or later, replace the guessed weighting with your real one this sprint. Pull the bounce rate from analytics and set firstPageLoadPriority to it rather than leaving 0.67 in place. Add your product and cart routes to priorityRoutes. Define a cluster covering the category to product to cart path so those chunks merge more readily. Then turn on turbopackSharedRuntime and turbopackCjsTreeShaking, and measure requests and transferred JavaScript across a scripted funnel walk rather than a single Lighthouse run on the homepage. A single-page audit will reward exactly the wrong configuration.
Treat the numbers above as a method, not a target. They came from a documentation site with a long tail of shared components. A store with a heavy product page and a light category page will land somewhere else entirely. The point of the new flags is that the shape of your traffic is now an input to the build, and nobody at Vercel knows that shape better than your analytics do.
If you are on Hyvä, do nothing here. Spend the same hour on the parts of the page that actually block paint, which on a Magento storefront is almost always images, third-party tags and an over-eager consent script rather than the framework.
Where to dig deeper
- How Turbopack chunks your JavaScript, the September 3 post with the full comparison table.
- turbopackChunking config reference for the flag names and accepted values.
- Hyvä getting started docs for the Alpine and Tailwind baseline.