# 10 — Bundle Analysis · Unified Platform (2026-09-18)

**Method:** full production build reproduced in the clean throwaway copy (VPS, app image). Output is **byte-identical to the served bundle** (same chunk hashes: `index-DoLPDwpa.js`, `Admin-BXCRttRK.js`, `Schedule-DUL9XDLy.js`) — proving the deployed dist matches this source exactly.

## Totals
- `dist/` = **8.0 MB**, **58 JS chunks + 58 pre-compressed `.gz`** (+ css/font assets). gzip pipeline (`gzip-assets.mjs`) runs as part of build ✓; server serves `.gz` with `Content-Encoding` + immutable cache headers.
- 116 files in `dist/assets` (chunks + their `.gz`). `dist.old` (3.3 MB) left on the live tree (hygiene).

## Top chunks (raw → gzip)
| Chunk | Raw | Gzip |
|---|---|---|
| `Schedule-DUL9XDLy.js` | 567.6 KB | 99.4 KB |
| `vendor-charts` (recharts) | 435.2 KB | 117.0 KB |
| `vendor-xlsx` (@e965/xlsx) | 363.9 KB | 123.2 KB |
| **`Admin-BXCRttRK.js`** | **349.7 KB** | **56.1 KB** |
| `index` (app shell) | 335.3 KB | 83.6 KB |
| `vendor-react` | 326.9 KB | 99.2 KB |
| `Dashboard` | 147.2 KB | — |
| `index.css` | 141.6 KB | — |

## Findings
| # | Finding | Sev |
|---|---|---|
| B-1 | **Admin lazy-split regression.** `Admin.tsx` has ZERO `lazy()` imports; every admin tab is eager → 349.7 KB chunk (Aug-21 state: 83.2 KB after splitting 9 tabs). Re-applying the split is a mechanical, proven fix (same commit as FIX-14 pattern). | **P2 (perf)** |
| B-2 | `vendor-xlsx` (364 KB) and `vendor-charts` (435 KB) are chunked vendored, but xlsx is only needed inside BulkImport flows — confirm it's behind a dynamic import (it chunk-splits as vendor-*, so only fetched when the importing chunk loads). OK structurally; note as "verify lazy path" in backlog. | P3 |
| B-3 | Google Fonts (Inter/JetBrains Mono) fetched from `fonts.googleapis.com` — external dependency on a PHI-adjacent platform; self-hosting the two families removes a third-party call + a render-blocking hop. | P3 |
| B-4 | `dist.old` (3.3 MB) + multiple historical `_bak-*` dirs on the live tree — disk hygiene. | P3 |

## Note on Lighthouse
Public-page Lighthouse is run in the S4 pass (login page + `/public-schedule`); auth-gated pages cannot be lightshoused without an authenticated session — recorded honestly rather than estimated. Scores land in `index.json` + report.
