Shipping React apps that actually load fast in 2026
A practical checklist for getting Lighthouse from 60 to 99 — bundle splitting, server components, image strategy, and the unsexy CSS work that actually moves the needle.
ReactPerformanceViteNext.jsWeb Vitals
Performance is a team sport. The reason most React apps feel sluggish in 2026 isn't React — it's everything else: a 600KB JS bundle on first paint, hero images shipped at 4K, fonts that block render, and a hydration cascade that locks the main thread for two full seconds.
The boring wins (do these first)
1. **Image strategy.** Serve AVIF with a WebP fallback. Set width and height on every <img>. Lazy-load anything below the fold.
2. **Font loading.** `font-display: swap`, preload one weight, subset to the characters you actually use.
3. **Code splitting.** Route-level by default, component-level only where the bundle warrants it. Don't lazy-load tiny components — the request roundtrip costs more than the bytes you save.
4. **Defer non-critical JS.** Analytics, chat widgets, marketing pixels — all of them load after `load`, never before.
The architectural wins
Move data fetching to the server. React Server Components, server actions, or just a plain old SSR endpoint — the goal is to ship HTML the user can read before JS hydrates. Hydration is no longer free; treat it like a precious budget.
What we measure
LCP under 2s, INP under 200ms, CLS under 0.05. That's the minimum bar at Bug Bakery. Anything worse and we don't ship.