Who this is for. The developer adding a feature with JavaScript of its own, deciding whether it goes into an existing bundle or a new one. Afterwards you can read a site's bundle split, measure a candidate, and justify a new entry or decline one.
Why split by page type
One site-wide bundle is simple, and it makes every visitor pay for every feature: the home page downloads the checkout, the course player and the form engine. Splitting by page type keeps the code every page needs in a small shared set and moves heavy, single-purpose code into bundles that only the templates needing them load. The split follows the templates, not the source folders: a bundle exists because a template asks for it.
A real bundle table
A medium Smarty site built with gulp and webpack, measured on its committed production files with gzip -9:
| Bundle | Loaded by | Gzipped |
|---|---|---|
layout, components, integrations, ui | The base template, on every page (and the checkout's own base template) | about 33 KB together |
cart | The cart template | 8 KB |
checkout | The single-page checkout template | 92 KB |
payment | The payment-processing template | 1 KB |
forms | Queued by the form include, so only pages with a form load it | 77 KB |
lms | The course, book-page and test templates | 183 KB |
my-account | The account area, queued from an include every account template uses | 181 KB |
A content page loads about 33 KB of JavaScript. Without the split it would also load the forms, checkout, course and account code, about 540 KB gzipped, for nothing.
A larger Twig site splits along a different line: one entry per landing-page family and one per brand, each pairing a TypeScript entry with an SCSS entry, so a campaign page carries only its own code. The principle is the same.
When a new bundle is justified
Make a new entry when all three hold:
- the code serves one page type, or a feature switched on for only some pages;
- it is heavy enough to matter: tens of kilobytes gzipped, not a few;
- the pages that need it can be identified by template, so one template can load it.
Otherwise add the code to an existing bundle. Every bundle is another request, another <script> tag that must carry the nonce and the cache-buster, and another file to keep in the committed output. A feature used on many page types but only after an interaction, a phone-number widget or a payment SDK, is better as a dynamic import inside an existing bundle than as an entry of its own.
Measuring a candidate
Build for production and measure the file the browser will receive: