PR 10829: three more pages without NgModules

This finishes the single-component feature modules. /advertise, /global/category-creator-listing, and the marketing-pro pages now load their components without a module and a routing module in between. Six files are gone, and nothing a user sees should change.

topfan/TopFansLite-WebFrontend#10829 base hotfix/release-0.0.23/21-code-refactors 12 files, +26 −124

What changed

Before this PR, each page needed three files. A component declared with standalone: false, an NgModule that declared it, and a routing module with a single route. Now the component lists its own imports, and the router loads it directly.

PageURLsNow loads withComponent imports
advertisement-home /advertise loadComponent CommonModule, SharedModule, FaqComponent, ButtonComponent
global /global/category-creator-listing loadChildren with global.routes.ts CommonModule, SharedModule
marketing-pro-page /pro, /refer, /apps/* loadComponent, generated CommonModule, MarketingPageSharedModule, FaqComponent

advertisement-home dropped six unused imports

Its module imported form, select, modal, accordion, multiselect, and video modules. The template uses none of them. It uses buttons, the FAQ, a circle icon, and two directives from SharedModule.

Before, the module
imports: [
  FormsModule,
  NgSelectModule,
  ModalModule,
  AccordionModule,
  NgMultiSelectDropDownModule.forRoot(),
  NgIvsModule,
  SharedModule,
  CommonModule,
  FaqComponent,
  ButtonComponent,
  AdvertisementHomeRoutingModule
]
After, the component
@Component({
  selector: 'app-advertisement-home',
  imports: [
    CommonModule,
    SharedModule,
    FaqComponent,
    ButtonComponent
  ]
})

If the template had needed one of the dropped modules, the build would have failed. Standalone components don't get CUSTOM_ELEMENTS_SCHEMA from anywhere, so an unknown tag is a compile error. The build passed.

global kept a routes file

The other pages had a child route with an empty path, so the component could move up to the parent route. global's child route has a real path, category-creator-listing. The app route stays global with loadChildren, and the child moved into a plain Routes array. link-in-bio-fan-preview did the same in PR 10826.

- import('./modules/global/global.module').then((m) => m.GlobalModule)
+ import('./modules/global/global.routes').then((m) => m.GLOBAL_ROUTES)

The module also imported RouterModule, but the template has no router directives, so the component doesn't import it.

Marketing-pro routes are generated

scripts/prefetch-marketing-pages.mjs runs before every QA, staging, and prod build. It fetches published pro pages and writes marketing-pro-page-routes.generated.ts. Pro slugs can be nested, like apps/music-artists-fan-club, so the script builds a tree. Parent segments get children, and each leaf loads the page. The PR changes the leaf template in the script and the committed generated file together.

I found a stale file along the way. The committed routes list two /apps/* pages, but the committed data file only has apps/music-band-fan-club. So on a local build without a fresh prefetch, the pro pages load the component, find no data, and redirect to not-found. This was already true before the PR. Deployed builds regenerate both files, so they don't hit it.

What stayed the same

  • Route data. The marketing-pro component finds marketingProSlug by walking up route.parent. The data now sits on the component's own route, one step closer.
  • Case-insensitive URLs. The apps parent has children, so it matches a prefix. Each leaf has no children array and must match the rest of the URL. That was true for the old loadChildren leaves too.
  • The category listing's data. The search bar puts the chosen category in DataService, then navigates. DataService is a root singleton with a BehaviorSubject, so the standalone component reads the same instance.
  • Initial bundle. 12.30 MB on both the base branch and this branch.

How it was tested

I built the base branch and this branch with ng build --configuration=qa --prerender=false, started the SSR server from each, and requested the same URLs.

URLBaseThis PR
/advertise200, app-advertisement-homesame
/Advertise404same
/global/category-creator-listing200, app-creator-category-listingsame
/global200, falls through to a later routesame
/apps/music-artists-fan-club404, stale datasame
/apps/sports-teams-nil-collectives-membership404, stale datasame

Then I ran npm run prefetch-pages-qa to get fresh data and rebuilt. The script wrote loadComponent for all six pro routes, top-level and nested. None of the three generated route files uses loadChildren anymore.

URL, fresh QA dataResult
/pro200, page, FAQ, contact form
/refer200, page only
/apps/music-artists-fan-club200, page, FAQ, contact form
/Apps/Music-Artists-Fan-Club200, page, FAQ, contact form
/apps/music-band-fan-club200, page, FAQ, contact form
/apps/sports-teams-nil-collectives-membership200, page, FAQ, contact form

/refer hiding the FAQ and contact form is intentional. The template skips both when the slug is refer. I reverted the regenerated data afterward, so the PR doesn't include it.

Affected areas

All three are public pages. Nobody needs to log in to test them.

AreaRiskWhy
Advertise page Medium Six imports removed. The build proves the template compiles, but only clicking proves the buttons and FAQ behave after hydration.
Category creator listing Medium Reached from the header search bar, with state passed through a service. It has search, infinite scroll, and a back button.
Marketing-pro pages Low Same imports as before, minus the module wrapper. The route shape changed in a generated file.
Prefetch script Low Runs before every deployed build. Already exercised against QA.

Verification checklist

Test each page two ways. Load the URL directly, which renders on the server and then hydrates. Then reach it by clicking from another page, which makes the browser fetch the lazy chunk. My curl test only covered the first way. Checks are saved in this browser.

0 of 0 checked

Medium Advertise page, /advertise

Medium Category creator listing, /global/category-creator-listing

Low Marketing-pro pages, /pro, /refer, /apps/*

Low Prefetch script

On every page

Not tested

  • Nobody has clicked through these pages in a browser yet. That's what the checklist is for.
  • No white-label project was built.

What's next

No single-component feature modules are left. The remaining ones have 3 to 75 components each, and every one of them imports SharedModule. I'd make SharedModule's 147 declarations standalone before converting those, so each new component can import only what it uses.