Step 1-2 (audit + plan): classified 35 project markdown files into Core/Architecture/ADR/Temporary-audit/Sprint-report/Generated-review/ Duplicate/Obsolete/Historical. Agent-tooling files (.agents/skills/**, .superpowers/**, docs/context/**, CLAUDE.md/GEMINI.md/AGENTS.md/ .github/copilot-instructions.md) explicitly out of scope — intentional per-tool duplication, not documentation debt. Step 3 (merge, no information lost): - docs/PROJECT.md -> docs/PROJECT_INDEX.md, rewritten as the single entry point: system overview, living-doc index, archive pointer, current status, and a critical-finding callout up top. - docs/backend/BACKEND-INTEGRATION.md -> docs/BACKEND_API.md, docs/backend/REMAINING-BACKEND-WORK.md -> docs/BACKEND_API_REMAINING_WORK.md (also folded in a legitimate uncommitted status update that had been sitting unstaged all session: categories marked DONE, order-creation endpoint noted done). - RELEASE-NOTES.md merged into CHANGELOG.md (was a near-duplicate of the same release content in friendlier prose), then deleted. - KNOWN-ISSUES.md: added item 13 (see below) and item 14 (missing canDeactivate on admin/products edit, from the archived PROJECT-STATE audit, re-verified still true); added a correction note to Fixed item 7. - All cross-references to renamed/moved files fixed across every kept doc (grep+sed pass, then verified with a link-existence check across all 58 in-scope markdown files -> 0 broken links). Step 4 (archive, nothing deleted without merging first): created docs/archive/, moved 19 files there (3 root sprint reports, 1 platform report, SPRINT-PLAN.md, and 14 one-off audit/review/report docs). Added correction headers to the 3 archived docs whose conclusions were affected by the finding below, rather than silently leaving them misleading. Step 5: docs/PROJECT_INDEX.md rewritten per the mission brief - someone opening the repo should understand the whole system from it. IMPORTANT FINDING (surfaced during this audit, not the mission's primary goal but too significant to bury): pages/category/*, pages/search/*, pages/item-detail/*, pages/info/**, pages/legal/** (40+ files) are entirely unrouted dead code - app.routes.ts's cmsContentRoutes is a literal empty array, and category/search/product routes redirect to CatalogContainerComponent/ ProductDetailsContainerComponent, not these files. Confirmed against app.routes.ts directly and cross-checked against FRONTEND.md's own routing description. This means several fixes from earlier this cycle (RC-Premium-01, RC STORE-01) and the dead-code cleanup sprint's conclusion that these files were live were all wrong - documented as KNOWN-ISSUES.md item 13, flagged at the top of PROJECT_INDEX.md, and noted on the 3 archived docs whose conclusions it affects. No application code was changed to fix this (out of scope per this session's 'documentation only' constraint) - it needs a wire-it-up-or- delete-it decision first. Verification: tsc --noEmit clean, npm run build green, all markdown links across 58 in-scope files resolve (checked programmatically). No application/Angular/backend code modified. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.7 KiB
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 usetakeUntilDestroyed(this.destroyRef)or an explicitSubscription+ngOnDestroyunsubscribe. 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 requirestrackon, so there was nothing to fix. Legacy*ngForwithouttrackBy: zero occurrences.- Duplicate HTTP calls:
CategoryFacadeandConfigServicealready cache viashareReplay({bufferSize:1, refCount:true}), applied consistently — no duplicate-request pattern found. - Flagged, not fixed: 2
combineLatestsites (catalog-container.component.ts,subcategories.component.ts) are narrow, already-minimal RxJS composition — converting tocomputed()would touch adjoining facade state shape, judged out of this pass's risk budget. Per-item template method calls in@forloops (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.tsusesloadComponent, nothing eagerly imported. - i18n eager-loading — the biggest single win:
TranslateServicestatically 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/hyare nowimport()ed on demand via a newpreloadLanguage(), awaited insidelanguageGuardbefore route activation — router blocks navigation until the pack resolves, so there's no untranslated-flash risk. - Dead code:
knipfoundsrc/app/components/items-carousel/*(3 files) completely unreferenced anywhere, and the sole consumer of theprimengdependency. Deleted the component and its now-deadprimeicons.cssimport fromsrc/styles.scss. - Tree-shaking: fixed one accidental barrel import in
widget-host.service.ts(now importsUnknownWidgetComponentdirectly instead of through thewidgets/uibarrel) — negligible measured impact, but correct going forward.@lucide/angularicons already use named tree-shakeable imports. - Duplicate deps:
npm lsconfirms a single dedupedrxjs@7.8.2— no duplicate module instances. - Flagged, not fixed:
primeng/primeiconsremain inpackage.json/lockfile —npm install/uninstallfails in this environment (ETARGET) on a pre-existing, unrelated brokenbarry-cachedevDependency, so the lockfile couldn't be safely regenerated by hand. Follow-up needed: fix thebarry-cachedevDependency resolution, thennpm uninstall primeng primeiconsto drop the dependency entirely (the code reference is already gone). Large chunks (project-editor320 kB,catalog-container126 kB,product-details-container88 kB,cart61 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 haveloading="lazy"/decoding="async"on grids/galleries and CLS is already handled via CSSaspect-ratio(from prior RC-Visual-02/RC-Premium-01 passes) — nothing to fix. Flagged: a handful of single-image admin/editor previews lackloading="lazy"(page-editor, brand-overview, asset-details-drawer) — negligible traffic, left alone. - Fonts:
index.htmlalready preconnects to Google Fonts, loads DM Sans 400/500/600/700 withdisplay=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/angularviaicon-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 insrc, 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) ofsrc/styles.scssutility 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)
primeng/primeiconsstill inpackage.jsondespite the only consumer being deleted — needs the pre-existingbarry-cachedevDependency resolution issue fixed first, then a cleannpm uninstall. Highest-value remaining action: would likely close most of the remaining 417 KB budget overage in one move once confirmed.- Large lazy chunks (
project-editor320 kB,catalog-container126 kB) — no mechanical fix found; needs a dedicated task to identify a genuinely lazy-loadable sub-feature inside each. - 2
combineLatestsites — safe to leave, candidates for acomputed()conversion in a future facade-focused pass. - Per-item template method calls in
@forloops — pipe-conversion candidates, not urgent (already bounded by OnPush). - 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.
- 5 unreferenced branding SVGs — confirm with backend/tenant-branding owner before deleting.
- 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.