docs: add PERFORMANCE_REPORT.md for RC PERF-01
Consolidates the 3 perf-audit commits (reactivity/change-detection, bundles/lazy-loading/tree-shaking, assets) into one report: headline 1.47MB->1.12MB initial bundle (-24%), plus per-area findings and a remaining-work list (primeng/primeicons still in package.json pending a blocked npm uninstall, large lazy chunks, combineLatest sites). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
55
docs/PERFORMANCE_REPORT.md
Normal file
55
docs/PERFORMANCE_REPORT.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Performance Report — RC PERF-01
|
||||
|
||||
Production-readiness performance audit + fixes, application-wide. No redesign, no UI/visual changes, no route/API changes — pure performance/correctness work. Three sequential commits on branch `B2B` (not pushed):
|
||||
|
||||
| Commit | Scope |
|
||||
|---|---|
|
||||
| `61a5714` | Angular reactivity, change detection, rendering, memory |
|
||||
| `4bf0666` | Bundles, lazy-loading, tree-shaking, large chunks |
|
||||
| `2e931bb` | Assets: images, fonts, SVG, CSS |
|
||||
|
||||
`npm run build` verified green after every commit. `npx tsc --noEmit` clean throughout.
|
||||
|
||||
## Headline result
|
||||
|
||||
Initial bundle: **1.47 MB → 1.12 MB raw** (−350 KB / −24%), transfer estimate **263.59 kB → 221.51 kB** (−16%). Budget overage shrank from 769 KB over to 417 KB over (still a warning, not an error — the 700 KB budget itself is unchanged and still exceeded, see Remaining below). Global CSS bundle: 9.60 kB → 8.41 kB raw (−12%).
|
||||
|
||||
## Findings and fixes by area
|
||||
|
||||
### Angular reactivity / change detection / memory (`61a5714`)
|
||||
|
||||
- **`.subscribe()` audit**: 149 call sites across 44 files. Spot-checked every long-lived stream in the highest-risk components (route params, router events, polling/intervals) — all already use `takeUntilDestroyed(this.destroyRef)` or an explicit `Subscription` + `ngOnDestroy` unsubscribe. One-shot HTTP-backed subscribes self-complete, no leak. **No leaks found** — the codebase's existing discipline here was already solid.
|
||||
- **`ChangeDetectionStrategy.OnPush`**: 191 components, 190 already had it. Added to the 1 remaining (`app.ts`, the root component) — verified safe (signal-driven template, no direct DOM mutation).
|
||||
- **`@for`/`track`**: fully compliant app-wide — the codebase is entirely on the new control-flow syntax, which the compiler requires `track` on, so there was nothing to fix. Legacy `*ngFor` without `trackBy`: zero occurrences.
|
||||
- **Duplicate HTTP calls**: `CategoryFacade` and `ConfigService` already cache via `shareReplay({bufferSize:1, refCount:true})`, applied consistently — no duplicate-request pattern found.
|
||||
- **Flagged, not fixed**: 2 `combineLatest` sites (`catalog-container.component.ts`, `subcategories.component.ts`) are narrow, already-minimal RxJS composition — converting to `computed()` would touch adjoining facade state shape, judged out of this pass's risk budget. Per-item template method calls in `@for` loops (`getDiscountedPrice`, `itemName`, `categoryName`, `stockLabelKey`) are cheap pure lookups on an already-OnPush host — flagged as pipe-conversion candidates for a future pass, not urgent.
|
||||
|
||||
### Bundles / lazy-loading / tree-shaking (`4bf0666`)
|
||||
|
||||
- **Lazy-loading boundaries**: already correct — every storefront/builder/backoffice route in `app.routes.ts` uses `loadComponent`, nothing eagerly imported.
|
||||
- **i18n eager-loading — the biggest single win**: `TranslateService` statically imported all three locale packs (ru/en/hy, 346 KB raw combined) into the initial bundle regardless of visitor language. Fixed: `ru` (default) stays eager, `en`/`hy` are now `import()`ed on demand via a new `preloadLanguage()`, awaited inside `languageGuard` before route activation — router blocks navigation until the pack resolves, so there's no untranslated-flash risk.
|
||||
- **Dead code**: `knip` found `src/app/components/items-carousel/*` (3 files) completely unreferenced anywhere, and the sole consumer of the `primeng` dependency. Deleted the component and its now-dead `primeicons.css` import from `src/styles.scss`.
|
||||
- **Tree-shaking**: fixed one accidental barrel import in `widget-host.service.ts` (now imports `UnknownWidgetComponent` directly instead of through the `widgets/ui` barrel) — negligible measured impact, but correct going forward. `@lucide/angular` icons already use named tree-shakeable imports.
|
||||
- **Duplicate deps**: `npm ls` confirms a single deduped `rxjs@7.8.2` — no duplicate module instances.
|
||||
- **Flagged, not fixed**: `primeng`/`primeicons` remain in `package.json`/lockfile — `npm install`/`uninstall` fails in this environment (`ETARGET`) on a pre-existing, unrelated broken `barry-cache` devDependency, so the lockfile couldn't be safely regenerated by hand. **Follow-up needed**: fix the `barry-cache` devDependency resolution, then `npm uninstall primeng primeicons` to drop the dependency entirely (the code reference is already gone). Large chunks (`project-editor` 320 kB, `catalog-container` 126 kB, `product-details-container` 88 kB, `cart` 61 kB) unchanged — no mechanical split found inside their scope; a real reduction here would mean lazy-loading a sub-feature (e.g. an embedded editor), which is a larger, dedicated task.
|
||||
|
||||
### Assets: images, fonts, SVG, CSS (`2e931bb`)
|
||||
|
||||
- **Images**: storefront `<img>` tags already have `loading="lazy"`/`decoding="async"` on grids/galleries and CLS is already handled via CSS `aspect-ratio` (from prior RC-Visual-02/RC-Premium-01 passes) — nothing to fix. Flagged: a handful of single-image admin/editor previews lack `loading="lazy"` (page-editor, brand-overview, asset-details-drawer) — negligible traffic, left alone.
|
||||
- **Fonts**: `index.html` already preconnects to Google Fonts, loads DM Sans 400/500/600/700 with `display=swap`; all 4 loaded weights are actually used. Flagged: weights 800/900 are referenced in some component SCSS but never loaded (pre-existing faux-bold rendering) — changing loaded weights risks a visible text difference, left out of scope for a perf-only pass.
|
||||
- **SVG**: icon system is fully centralized through `@lucide/angular` via `icon-registry.ts` — no inline path duplication. `public/` SVGs checked for editor cruft (metadata/inkscape artifacts) — already clean. Flagged: 5 branding SVGs (`mastercard-logo.min.svg`, `dexar-logo*.svg`, `dexar-favicon.svg`, `novo-logo.svg`, `novo-favicon.svg`) appear unreferenced in `src`, left in place — may back tenant branding resolved from the backend at runtime, deletion needs a human decision, not this pass's call.
|
||||
- **CSS**: manual grep-based cross-check (literal + hyphen-safe, checked for dynamic `[class.x]`/string-built classes too) of `src/styles.scss` utility classes against all templates. Confirmed-dead and removed: `.btn-primary`/`.btn-secondary`+hover, `.catalog-product-card`, `.item-badges-overlay`, `.item-simple-desc`, `.text-center`, `.mt-1..4`, `.mb-1..4`, `.p-1..4`.
|
||||
|
||||
## Remaining recommendations (not applied — flagged for follow-up)
|
||||
|
||||
1. **`primeng`/`primeicons` still in `package.json`** despite the only consumer being deleted — needs the pre-existing `barry-cache` devDependency resolution issue fixed first, then a clean `npm uninstall`. Highest-value remaining action: would likely close most of the remaining 417 KB budget overage in one move once confirmed.
|
||||
2. **Large lazy chunks** (`project-editor` 320 kB, `catalog-container` 126 kB) — no mechanical fix found; needs a dedicated task to identify a genuinely lazy-loadable sub-feature inside each.
|
||||
3. **2 `combineLatest` sites** — safe to leave, candidates for a `computed()` conversion in a future facade-focused pass.
|
||||
4. **Per-item template method calls** in `@for` loops — pipe-conversion candidates, not urgent (already bounded by OnPush).
|
||||
5. **Font weights 800/900** used in SCSS but not loaded — either load them explicitly or normalize the SCSS to a loaded weight; a design-system call, not a perf call.
|
||||
6. **5 unreferenced branding SVGs** — confirm with backend/tenant-branding owner before deleting.
|
||||
7. **Admin/editor preview images** missing `loading="lazy"` — low priority, low traffic.
|
||||
|
||||
## Verification
|
||||
|
||||
`tsc --noEmit` and `npm run build` run and green after each of the three commits. No live browser session available this session — real-world Core Web Vitals (LCP/CLS/INP) were not measured; recommend a Lighthouse/WebPageTest pass against a deployed build before the client demo referenced in `docs/FRONTEND-ROADMAP.md`.
|
||||
Reference in New Issue
Block a user