PR 10829: standalone routes review

PR 10829 converts the last three single-component modules (advertisement-home, global, marketing-pro-page) to standalone routes, deletes six module files, and makes the pro-page generator write loadComponent. One commit, 13 files, +35 / -124. I read every file, built the head, and rendered nine routes over SSR.

Verdict

Merge it. The build is clean, the bundle is unchanged at 12.30 MB, and every route renders what it rendered before. Nothing in the diff surprised me. The two things I would change are older than this PR.

reviewed 2026-09-23 base d62b682fab head 93006eee3c Angular 21.2.23

What changed

/advertise uses loadComponent. /global still uses loadChildren, now pointed at a new global.routes.ts, because its only page lives at a child path. The pro-page generator in prefetch-marketing-pages.mjs writes loadComponent, and the committed generated file was hand-edited to match. Each component gained an imports array holding what its template uses.

Findings

correct

The imports cover the templates

I traced every element and directive in the three templates. app-circle-background-icon, appDisableRightClick, and appMobileOptimization come from SharedModule. app-marketing-page-full-preview and app-pro-contact-form-layout come from MarketingPageSharedModule. app-faq and app-button are imported directly. The rendered /advertise page contains all of them with their inner markup, so this holds at runtime, not only in the compiler.

correct

The dropped modules were dead weight

The old AdvertisementHomeModule imported FormsModule, NgSelectModule, ModalModule, AccordionModule, NgMultiSelectDropDownModule.forRoot(), and NgIvsModule. The template uses none of them and the component injects nothing they provide. GlobalModule imported RouterModule for a template with no routerLink. Someone copied a module header years ago and nobody looked again. Good riddance.

correct

CUSTOM_ELEMENTS_SCHEMA is gone

MarketingProPageModule had it. The standalone component does not, so the compiler now checks that template fully. The AOT build passes with no NG8001 or NG8002. Same bar 10826 set.

correct

One chunk for global

global.routes.ts uses component: with a static import. The build puts GLOBAL_ROUTES and the component in one 6.5 KB chunk. That is the right call; the two-hop split in 10827 was the main reason that PR lost.

correct

Route data and stale references

resolveMarketingProSlug() walks route.parent until it finds marketingProSlug, so it works under both the old and new route shape. I searched the head for the six deleted class names and file paths. Nothing left.

note

The committed pro data and routes disagree

marketing-pro-page-data.ts has one slug. marketing-pro-page-routes.generated.ts has two different ones. Build from the committed files and every pro page 404s or falls through to app-sub-page-view. The PR says so and is right that deployed builds are fine because they prefetch first. Still, this has been wrong since July and someone should commit a matching pair, or derive the routes from the data so they cannot drift.

note

SharedModule for three things

Two components import all 160-odd SharedModule exports to get one component and two directives. Their old modules did the same, so nothing regressed. Worth narrowing once more of the app is standalone.

What I ran

Checked out the head in a worktree and ran ng build --configuration=qa --prerender=false. Passed in 48 seconds with only the usual budget and non-ESM warnings. Then started server.mjs and fetched these:

  • /advertise200app-advertisement-home, FAQ and buttons rendered
  • /Advertise404not case-insensitive, same as base
  • /global/category-creator-listing200app-creator-category-listing
  • /global200falls through to :id, same as base
  • /apps/music-artists-fan-club404route exists, data does not
  • /apps/music-band-fan-club200app-sub-page-view; data exists, route does not
  • /pro404not in committed routes
  • /refer404not in committed routes

Not run: the base build, the prefetch script, a browser, prerender, white-label builds.

QA after merge

  1. /advertise: buttons open the advertiser site in a new tab, FAQ expands.
  2. /global/category-creator-listing: reach it from the search bar, filter the list, scroll to load more.
  3. On a QA build, open /pro, /refer, and one /apps/* page. Sections render, contact form submits.
  4. Run npm run prefetch-pages-qa and confirm the pro routes file has no loadChildren.