What a layout is
Think of a printed magazine page. One page might have a big title photo, a quote, and a list of products. Those are different templates. In this app they are Angular components with names like hero, testimonials, store-items-grid, and comparison-full-table.
There are 55 layout ids in the catalog. The public preview has a component for 54 of them. pro-contact-form is the missing one. Creators pick from this list when they build a marketing page, a comparison page, a pro page, or a white-label cover.
What happens today
One component draws every public marketing page. MarketingPageFullPreviewComponent. It loops the page's sections. For each section it reads a layout id and switches to that component.
Angular only lets a template use a component that the parent imported. So the preview file imports all 54 classes and lists all 54 in its imports array. The switch can then render any of them. The bundler sees 54 static imports, so it puts all 54 in the same JavaScript the page downloads.
A page that uses a header, a hero, and a footer still pays for the passion grid, the portfolio album block, and the comparison table. Those files run no code on that visit. They still travel over the wire.
Which pages pay
Anything that renders through that preview component:
- The main site's
/ /marketing- The comparison pages
- The pro pages
- Creators-home
- A white-label cover page
The editor that lets a creator add a section also imports the full list. That is the right call. A creator opening the picker needs every type. The waste is the public pages using the same graph.
What it cost after 10847
First-visit JavaScript after the initial bundle, from the QA build after PR 10847. MB means a million bytes, before compression. After the layout split these entries are 1.76, 0.03 to 0.86, and 0.11 to 0.21 MB. See the notes.
| Page | After 10847 |
|---|---|
Main site / | 2.79 MB |
| Marketing | 1.23 MB |
| Comparison | 1.23 MB |
| Pro | 2.05 MB |
| Creators-home | 1.30 MB |
| Sub-page view | 1.36 MB |
Those numbers are the whole route, not layouts alone. Shared chrome sits in there too. The layouts are why the numbers stayed this high after we already took SharedModule and Profile off the home chunk.
What we would gain
The visitor would download only the layout types that page actually uses. Six types on the page means six layout files, plus the preview shell. The other 48 stay on the server until some other page needs them.
I will not invent a megabyte number. We have not split the files yet, so we have not measured the leftover. The direction is clear.
| Win | Who feels it |
|---|---|
| A thin page stops paying for layouts it never shows | First visit to home, marketing, comparison, pro, creators-home, and a cover page |
| A second marketing URL can reuse layouts the first page already fetched | Someone who goes from home to a comparison page that shares a hero and a header |
| A kitchen-sink page that uses 20 types shrinks less | Demo pages that stacked most of the catalog. That is expected. |
| The editor can keep all 54 | Creators. Their first open of the CMS still has every block in the picker. |
The win is first-visit JS. It is not a new feature and it is not a visual redesign. If a page looks different, the change is wrong.
How the fix would work
Stop importing the 54 classes at the top of the preview file. Keep a map from layout id to a dynamic import(). When the page knows its sections, start those imports together. Render each finished class with ngComponentOutlet.
The server has to wait for those imports before it writes HTML. We already did this for the white-label profile fallback, with PendingTasks. Skip that and the first HTML is missing <app-hero-layout>. The browser then fills it in. Search engines and the first paint see a hole. @defer has the same hole. It is the wrong tool on these public pages.
Verification checklist
After a change, the page must look the same and the unused layout files must stay off the wire. Keep the network panel and the console open. Checks are saved in this browser.