Guide 03 · Developer docs

The theme repo and the asset pipeline

Everything a developer changes on a Core dna site lives in its theme repository. This guide covers the repository and its build, printing records in templates, stylesheets and client-side code, and the parts of a site around the main content.

L1–L2
Unit 01 · Anatomy of a theme repo

Bundle boundaries

Sites split their JavaScript into a bundle per page type, so a content page never downloads the checkout. A real bundle table with the template that loads each bundle and its measured size, and the rule for when a new bundle is worth its cost.

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:

BundleLoaded byGzipped
layout, components, integrations, uiThe base template, on every page (and the checkout's own base template)about 33 KB together
cartThe cart template8 KB
checkoutThe single-page checkout template92 KB
paymentThe payment-processing template1 KB
formsQueued by the form include, so only pages with a form load it77 KB
lmsThe course, book-page and test templates183 KB
my-accountThe account area, queued from an include every account template uses181 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:

  1. the code serves one page type, or a feature switched on for only some pages;
  2. it is heavy enough to matter: tens of kilobytes gzipped, not a few;
  3. 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:

Shell Gzipped size of each built bundle
npm run prod
for f in dist/*.js; do printf '%-40s %8d\n' "$f" "$(gzip -9 -c "$f" | wc -c)"; done

Compare the bundle's size with and without the feature. If the difference is a few kilobytes, it does not need a bundle. Budgets that catch a bundle growing past its share are on Bundle budgets.

Go deeper

Was this page helpful?

Your answer goes to the docs team.