Port Resolve_build_size_19 onto this Angular 19 branch
Yes. Stay on Angular 19 and PrimeNG 17. Keep the lazy CSS you already shipped. Copy their JS splits. PrimeNG 19, Lara, and PrimeNgLoaderService wait for the Angular 20 upgrade. Measure after each slice so a broken import does not hide behind a smaller bundle.
Where you are
Current branch is feature/release-0.0.23/16-17-18-19 at eddf08efa8. package.json has @angular/core ~19.2.25 and CLI ~19.2.27. That is Angular 19.
PrimeNG is still ~17.18.15. Their size-fix branch is Angular 19.2.25 with PrimeNG 19.1.4 and @primeng/themes. Same Angular major. Different PrimeNG. That is the only hard mismatch.
This branch already has inject: false vendor CSS, LazyVendorCssDirective, and per-widget loadFor* calls. They do not. There is no @defer here. SharedModule still imports intl-tel, emoji-mart, color picker, timepicker, OTP, IVS, share buttons, mentions, all three video players, profile, post-submit, mobile-input, and custom-multiselect. The header still static-imports the three marketing JSON files.
Copy / skip
| From their branch | Here |
|---|---|
DeferredIntlTelInputComponent plus @defer (on idle), remove NgxIntlTelInputModule from shared |
Copy. Keep loadForIntlTel() and the directive. |
EmojiMartPickerComponent plus @defer (on immediate), remove PickerModule from shared |
Copy. Keep loadForEmojiMart(). |
Header await import() of marketing / pro / comparison data |
Copy. About 906 kB of source leaves the initial graph. |
Make video players standalone, drop them from shared declarations, @defer (on viewport) in post-card and profile |
Copy the idea. Do not copy their imports. Post-card is still an NgModule component. Import each standalone player into SharedModule.imports so the template compiles. Then measure. If video.js is still in initial, move the import onto post-card after it is standalone. |
| Move IVS, share buttons, mentions, timepicker, OTP, color picker, profile, post-submit, mobile-input, custom-multiselect out of shared and into the feature that uses them | Copy after the first three slices. This is the compile-error grind, and the rest of the 5 MB. |
@defer (on idle) around timepicker, color picker, mobile-input, custom-multiselect in the form builder |
Copy once those components are no longer exported from shared. |
Their isPlatformBrowser CSS loader and the app.component setTimeout(0) preload |
Skip. Keep the directive and the SSR <link> behavior you just fixed. |
PrimeNG 17 to 19, @primeng/themes, Lara, PrimeNgLoaderService |
Deferred. Do this during the Angular 20 upgrade. This branch keeps PrimeNG 17 CSS via lazy-primeng-theme / lazy-primeng / lazy-primeicons. |
1. Baseline
Record ng build --configuration=qa --prerender=false initial / lazy / styles. Prerender does not change chunk bytes. Do not commit the prefetch dirt in prerender.routes.txt, marketing generated files, or environment.ts.
2. Phone, then emoji, then marketing JSON
Three small, independent cuts. Do them in this order. Rebuild after each one.
- Add
src/app/components/deferred-intl-tel-input/. Only this file importsNgxIntlTelInputModule. Swap every<ngx-intl-tel-input>to@defer (on idle) { <app-deferred-intl-tel-input> }. Remove the module fromSharedModule. Call sites: mobile-input, personal-info, contact-us, advertise, customer-information. - Add
src/app/components/emoji-mart-picker/. Same pattern with@defer (on immediate)inside the existingshowEmojiPickerguard in messages and chat-comments. RemovePickerModulefrom shared. - In the header, delete the static imports of
MARKETING_PAGE_DATA,MARKETING_PRO_PAGE_DATA, andCOMPARISON_PAGE_DATA. Load them withawait import()in the three listing methods. PortapplyAsyncSafe()if SSR change detection complains.
Expect chunk-SA2WMUN6-class intl-tel to leave initial after step 1. Emoji and the 906 kB marketing files after 2 and 3. Phone fields will appear after idle. Emoji JS loads when the picker opens. Marketing nav links can fill one tick late.
3. Video players
Set standalone: true on v1, v2, and v3. Move them from SharedModule.declarations to SharedModule.imports. Add @defer (on viewport) with a placeholder in post-card and profile. Keep loadForVideoPlayer().
Click a feed video and a profile video before calling this done. Their size-fix branch removed the players from shared and left post-card as a module component with CUSTOM_ELEMENTS_SCHEMA. That can compile and still not instantiate the player. If video.js is still in the initial table, post-card is still dragging it. Make post-card standalone next and import the player only there.
4. The rest of SharedModule
One vendor or widget per commit. After you remove it from shared, the first build tells you every feature that still needs it. Put the import on that feature module or standalone component. Then wrap the form-builder cases in @defer (on idle).
Suggested order: color picker, timepicker, OTP, mentions, share buttons, IVS if the video slice did not already take it, mobile-input, custom-multiselect, post-submit, ProfileComponent.
Comments, welcome-video, sponsored-ad, and the alert-modal carousel can get viewport or idle @defer after that. Those are below-fold wins, not the initial-table win.
Deferred until Angular 20
Do not bump primeng, do not add @primeng/themes, and do not add PrimeNgLoaderService on this branch. PrimeNG 17 stays. Theme CSS stays on the existing lazy bundles and LazyVendorCssDirective.
When this app moves to Angular 20, that upgrade owns PrimeNG 20, the Lara preset, and whether Lara is eager in AppModule or loaded later. Doing it now would mix a theme migration into a module-graph cut.
Check after each slice
- QA compile with
--prerender=false. Initial raw should fall.stylesshould stay near 1.81 MB. Monetize / insights / messages should stay flat. - Contact-us and personal-info: phone field appears, validates, country picker works, flag CSS loads.
- Messages: emoji picker opens, CSS arrives, send still works.
- Public header: marketing, pro, and comparison listing links populate.
- Home feed and a profile: video plays, mute works, no empty custom element.
- A page with
p-carouselor custom-multiselect: PrimeNG 17 CSS still lands through the directive. - A toast still has toastr CSS. A datepicker still has bootstrap datepicker CSS.
Risks
- Removing something from
SharedModulewithout adding it at the use site. The build fails. That is the point. Fix the import, do not put it back in shared. - Video player
@deferwith no standalone import. Size looks good, player never boots. - Idle phone fields on a busy main thread. Short blank, then the input. Accept it or switch those sites to
on immediateif QA hates the hole. - Prerendered HTML will not contain deferred blocks. Phone was already client-only via
cs.isBrowser. Videos and emoji become client-only too. Fine for those widgets. Do not@deferSEO text. - Header marketing data becomes async. Possible empty mega-menu for one tick, and an extra SSR change-detection pass.
Assumptions
- Goal is a smaller first load on this Angular 19 branch, not a merge of
Resolve_build_size_19. - PrimeNG stays at 17 until the Angular 20 upgrade. Their 6.80 / 1.14 MB initial is the shape to chase, not a number this branch must hit. PrimeNG 17 vs 19 will not match byte-for-byte.
- Idle delay on phone and viewport delay on offscreen video are acceptable. Say so if they are not. Those triggers are easy to change after the splits exist.