The list
| Leftover | What I would do | Why |
|---|---|---|
| 54 marketing layout components on every public marketing page | Done | Marketing is 0.03 MB. Comparison is 0.03 MB. Home is 1.76 MB because promotional.routes still statically owns landing, detail, and search. The unused layouts stay off the wire. |
White-label cover pages still fetch ProfileComponent |
Ride along | The constructor starts the 1.85 MB profile import on every white-label site, including published cover pages that never render it. |
comparison-layout.utils imports the editor field file |
Ride along | A public preview helper pulls a 935-line editor constants file. Small. Same graph as the layouts. |
AppModule and AppServerModule |
Skip | Last two NgModules. High risk. Almost no download win. This is cleanliness, not a size change. |
| Post-price leftover after dashboard | Leave | About 4 KB. It is custom-input-list sitting with add-lock, not unused decorator imports. |
| Four portfolio info icons stay 16 pixels | Leave | Dead [infoIconSize] bindings. Visual, not a bundle issue. Always been this way. |
Older console.log calls |
Leave | Hygiene in files these steps already touched. Not a leftover of the plan. |
The 54 layouts
Done. The notes have the measured sizes. The code walk is the three files. The public preview loads unique visible layout ids with literal import() calls, renders them with ngComponentOutlet, and holds PendingTasks until they finish. Header stays static because it projects the welcome-video modal. The editor still imports the full catalog.
Marketing and comparison dropped to 0.03 MB. Home dropped to 1.76 MB, not because unused layouts still download, but because promotional.routes.ts still statically imports landing, promotional, promotional-detail, and search-result. SSR title, description, and app-*-layout counts match the 10847 HTML.
Cover pages still fetch Profile
PromotionalLandingComponent starts import('@shared/components/profile/profile.component') in the constructor whenever hasWhiteLabelConfig() is true. PendingTasks keeps SSR open until that chunk loads. That is correct for the profile fallback. It is wasted work on a site whose build flag says the cover page is published.
Before 10847 those sites already had Profile in the landing graph, so this is not a new download. We made it possible to skip the chunk and then did not skip it. On a published cover site, SSR also waits for 1.85 MB it will not put in the HTML.
The fix is to start the import in loadLanding() only when the landing state is the profile fallback. Keep PendingTasks on that path. Preview mode comes from query params after ngOnInit, so the constructor is the wrong place anyway.
This did not ride along with the layout split. I would still not make it its own PR unless we are already in that file.
The editor constants leak
comparison-layout.utils.ts is 162 lines of read helpers. Column labels, row indexes, logo application. Public cover preview imports it. So do the CMS section list and the editor.
Those helpers import field-name functions from comparison-page-section-layout-fields.constants.ts. That file is 935 lines and 29 KB of editor copy, plus form-builder field types. A visitor on a cover page does not need "Add Feature Block".
Move the read helpers into a file that does not import the editor. Leave the editor file on the CMS. This is a split, not a redesign. It did not go in the layout PR. It does not belong alone.
Why I would not do bootstrapApplication next
main.ts still calls bootstrapModule(AppModule). The server build wraps that in AppServerModule. server.ts, serverless.ts, and functions/index.js all name that module. provideZoneChangeDetection() lives in AppModule on purpose, so the server gets the same scheduler.
Moving to bootstrapApplication means rewriting client bootstrap, server bootstrap, hydration, the white-label APP_INITIALIZER, Stripe, Toastr, the store, and the service worker. Header, sidebar, footer, and Stripe stay in the initial bundle either way. The download does not move. The failure mode is "the app does not start" or "SSR HTML changes on every route".
Do it if the goal is "zero NgModules". Do not do it because a route is heavy. Those are different jobs.
The small ones
The post-price 4 KB leftover from PR 10841 is custom-input-list compiled with add-lock. Dynamic-importing the camera modal did not remove it. Pulling ImageCropper out of the decorator will not either. Splitting add-lock is a real change for a rounding error.
Four portfolio templates bind [infoIconSize]="18" on a component that has no such input. The icon stays 16 pixels. CUSTOM_ELEMENTS_SCHEMA used to hide that. Adding the input is a one-line visual fix if someone asks. It is not leftover SharedModule work.
Some files these PRs touched still have console.log from before. Stripping them is fine in a file we already have open. It is not a follow-up PR.
If we keep going
The layout leftover is done. I would not open a PR for the cover Profile fetch or the 29 KB editor constants unless we are already in those files. I would not start bootstrapApplication to shrink a route.
If we are done chasing first-visit JS, stop. The SharedModule plan is finished. Everything above is optional.