3.3 KiB
3.3 KiB
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 < 1024px
- GSAP scroll reveals skipped when
prefers-reduced-motion - Smaller hero
srcSetwidths selected by browser - Sticky ticket bar uses safe-area padding
Lighthouse (preview)
Measure against production build:
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
/apiand/media(backend) short_descriptiononEventSummaryto avoid featured detail fetch- Self-hosted fonts subset for Fraunces + DM Sans
- Service worker / offline (PWA)