Vite + React Performance 2026: The Complete Problem-Solving Guide
By Huzi
File #542 · 3 min read
The bundle is 2.5MB, the Lighthouse LCP reads like a phone number, and users on 3G watch a white screen while your unused lodash downloads. Vite 6 and React 19 hand you sharper tools — but none help until you measure, because a fast app on your machine and a fast app on a StormFiber evening are different animals.
The quick answer: Measure first — LCP under 2.5s, CLS under 0.1, INP under 200ms — then split routes with lazy imports and vendor chunks. Tree-shake lodash and icons, let the React Compiler handle memoization, and fix images before JavaScript.
Measure the three numbers that matter
LCP under 2.5 seconds, CLS under 0.1, INP under 200 milliseconds — Google's good thresholds, and ranking follows them. Lighthouse in DevTools gives the lab view; the web-vitals package gives you real users:
import { onLCP, onCLS, onINP } from 'web-vitals';
function send(metric: { name: string; value: number; rating: string }) {
fetch('/api/vitals', {
method: 'POST',
body: JSON.stringify(metric),
keepalive: true,
});
}
onLCP(send);
onCLS(send);
onINP(send);
Split what the visitor is not using yet
Route-level lazy loading is the highest-leverage split: a visitor landing on the home page should not download the dashboard. Lazy-import each route and wrap the router once in Suspense; Vite cuts every dynamic import into its own chunk automatically. Vendor chunks earn their keep separately — otherwise one line of app code invalidates the cache of every library you ship:
build: {
rollupOptions: {
output: {
manualChunks: {
'react-vendor': ['react', 'react-dom', 'react-router-dom'],
'chart-vendor': ['recharts'],
},
},
},
},
Kill the obvious bloat
import _ from 'lodash' ships the whole library; import { debounce } from 'lodash-es' ships a kilobyte or two. Same law for icons: import named icons from lucide-react, never the star import. When you cannot guess what is heavy, stop guessing — rollup-plugin-visualizer emits a stats.html treemap after every build, and the biggest rectangle is your afternoon's work.
Measure-first applies to trips too: the cheapest fare hides its true size in bags, transfers and 3 a.m. layovers. HTG Travels quotes the all-in number before you commit, the way you profile before you refactor.
Let the compiler do the memo work
React 19's compiler auto-memoizes components and inline functions at build time, retiring most of the useMemo and useCallback ritual. Enable it through the plugin config:
react({ babel: { plugins: ['babel-plugin-react-compiler'] } })
You write plain code; the build step remembers what changed. For heavy synchronous work the user types into — filtering thousands of rows — wrap the update in startTransition so keystrokes stay responsive while the expensive pass runs behind.
Images before JavaScript
A 4MB hero image sinks LCP regardless of your bundle. Serve AVIF with a WebP fallback, lazy-load everything below the fold, and give the hero loading="eager" plus fetchPriority="high" so it starts downloading before any script executes. Optimize images first, then code, then measure again — the number moving is the whole reward.
| Fix | The move | The payoff |
|---|---|---|
| Route splitting | Lazy-import routes, Suspense once | The dashboard never loads on home |
| Vendor chunks | manualChunks for react, recharts | One app line keeps library caches valid |
| Import hygiene | lodash-es, named lucide-react icons | Kilobytes instead of whole libraries |
| Compiler | babel-plugin-react-compiler | The useMemo ritual retired |
| Images | AVIF plus WebP fallback, eager hero | LCP saved before scripts run |
Pro tip: Track the 75th percentile per route, not the average. The average hides exactly the slow users the thresholds punish.
We obsess over a 200-millisecond response while, in Gaza, people measure their waits in hours at crossings for things the world moves freely — may their queues dissolve.
You optimise fast loops all week; someone should book you the slow lane. Our northern escapes — a Hunza week with no itinerary tighter than the tea breaks — are built at HTG Travels for people who spend their days shaving milliseconds. Ship the build, then let the mountains take their time — one line to +92 317 5054959.




