Desi-Clans/docs/PERFORMANCE.md
2026-10-08 02:52:58 +05:30

73 lines
3.3 KiB
Markdown

# Production performance — Desi Clans (public frontend)
**Last audit:** 2026-04-04
**Build:** `cd frontend && npm run build`
## Summary
| Area | Finding | Action taken |
|------|---------|--------------|
| **Bundle** | Admin + GSAP + Three on critical path | Route-level `React.lazy`, dynamic `loadGsap()`, isolated `hero-atmosphere` chunk |
| **Initial JS** | Single large entry | Split: `vendor-react`, `vendor-http`, `gsap`, `three`, per-route pages |
| **Images** | Full-width Unsplash URLs everywhere | `withImageWidth` / `srcSet` on hero, cards, featured, galleries |
| **Video** | None in app | N/A — no `<video>` on marketing site |
| **Fonts** | Google Fonts (2 families, limited weights) | `preconnect`, `display=swap` in CSS URL; no JS font loader |
| **API** | Home blocked on 2nd request for featured copy | List-only first paint; featured detail deferred via `requestIdleCallback` |
| **Caching** | Refetch on every navigation | In-memory TTL cache (60s) for events list, slug detail, venues |
| **GSAP** | Static import bloated entry | `loadGsap()` dynamic import on home + event detail only |
| **WebGL** | Large Three chunk | Desktop-only, idle mount, separate chunk; mobile = no download |
| **React** | Navbar scroll → many setState | `requestAnimationFrame` throttling |
| **CLS** | Hero / cards | Explicit `width`/`height` on hero; reserved route fallback shell |
## Production chunks (2026-04-04 build)
| Chunk | gzip (approx.) | When loaded |
|-------|----------------|-------------|
| `index-*.js` | **6.9 KB** | First paint (shell + router) |
| `vendor-react-*.js` | 79 KB | First paint |
| `vendor-http-*.js` | 19 KB | First API call |
| `HomePage-*.js` | 5.8 KB | Home route |
| `gsap-*.js` | 45 KB | After `loadGsap()` on home / event detail |
| `hero-atmosphere-*.js` | 124 KB | Idle + desktop only |
| `AdminRoutes-*.js` | 4.4 KB | `/admin` only |
**Before route split:** main `index` JS was ~**44 KB** gzip in one bundle with admin + pages.
**After:** entry shell ~**7 KB** gzip; admin/GSAP/Three not on marketing critical path.
Run `npm run build` and inspect `dist/assets/` for current gzip sizes.
## Lazy loading
| Asset | Strategy |
|-------|----------|
| Hero photo | `fetchpriority="high"`, preload 1600w, responsive `srcSet` |
| Event cards, categories, gallery, featured | `loading="lazy"`, `decoding="async"`, `sizes` |
| Event detail cover | `fetchPriority="high"` |
| Routes | `React.lazy` + `Suspense` |
| GSAP / WebGL | Dynamic import + idle callback |
## Mobile
- WebGL atmosphere **disabled** &lt; 1024px
- GSAP scroll reveals skipped when `prefers-reduced-motion`
- Smaller hero `srcSet` widths selected by browser
- Sticky ticket bar uses safe-area padding
## Lighthouse (preview)
Measure against production build:
```bash
cd frontend
npm run build && npm run preview -- --host 127.0.0.1 --port 4173
npx lighthouse http://127.0.0.1:4173/ --only-categories=performance,accessibility --chrome-flags="--headless"
```
Prior baseline (pre-split): ~86 performance / 96 a11y on home. Re-run after deploy; scores vary with network and Unsplash latency.
## Future (not in scope)
- CDN cache headers for `/api` and `/media` (backend)
- `short_description` on `EventSummary` to avoid featured detail fetch
- Self-hosted fonts subset for Fraunces + DM Sans
- Service worker / offline (PWA)