JavaScript
React.js Production Optimization Guide
Master React.js production optimization with performance tuning, bundle optimization, code splitting, SSR, caching strategies, monitoring, and enterprise deployment practices.
What you'll learn
- Analyse and reduce bundle size with code splitting
- Implement React.lazy and Suspense for route-level splitting
- Optimise re-renders with memo, useMemo, and useCallback
- Configure production builds for maximum performance
- Implement server-side rendering (SSR) and static generation
- Set up performance monitoring with Web Vitals
- Configure aggressive caching strategies
Bundle Optimisation
TypeScript
1// vite.config.ts — production build config
2import { defineConfig } from 'vite';
3import react from '@vitejs/plugin-react';
4
5export default defineConfig({
6 plugins: [react()],
7 build: {
8 rollupOptions: {
9 output: {
10 manualChunks: {
11 vendor: ['react', 'react-dom'],
12 router: ['react-router-dom'],
13 query: ['@tanstack/react-query'],
14 },
15 },
16 },
17 chunkSizeWarningLimit: 500,
18 sourcemap: false, // disable in production
19 minify: 'terser',
20 terserOptions: {
21 compress: { drop_console: true, drop_debugger: true },
22 },
23 },
24});Bash
1# Analyse bundle size
2npx vite-bundle-visualizer
3# or for webpack:
4npx webpack-bundle-analyzer stats.jsonRendering Performance
React TSX
1import { memo, useMemo, useCallback } from 'react';
2
3// Prevent unnecessary re-renders
4const ExpensiveList = memo(function ExpensiveList({ items, onSelect }: Props) {
5 return (
6 <ul>
7 {items.map(item => <li key={item.id} onClick={() => onSelect(item.id)}>{item.name}</li>)}
8 </ul>
9 );
10});
11
12function Parent() {
13 // Stable reference — doesn't change on every render
14 const handleSelect = useCallback((id: string) => {
15 // handle selection: id
16 }, []);
17
18 // Only recomputed when rawData changes
19 const processedItems = useMemo(
20 () => rawData.map(d => ({ id: d.id, name: d.name.trim() })),
21 [rawData]
22 );
23
24 return <ExpensiveList items={processedItems} onSelect={handleSelect} />;
25}Code Splitting
React TSX
1import { lazy, Suspense } from 'react';
2import { Routes, Route } from 'react-router-dom';
3
4// Each route is loaded only when navigated to
5const Dashboard = lazy(() => import('./pages/Dashboard'));
6const Settings = lazy(() => import('./pages/Settings'));
7const Analytics = lazy(() => import('./pages/Analytics'));
8
9export function AppRoutes() {
10 return (
11 <Suspense fallback={<PageSkeleton />}>
12 <Routes>
13 <Route path="/dashboard" element={<Dashboard />} />
14 <Route path="/settings" element={<Settings />} />
15 <Route path="/analytics" element={<Analytics />} />
16 </Routes>
17 </Suspense>
18 );
19}SSR & Static Generation
For marketing pages and content-heavy routes, use Next.js App Router server components for zero JS on the client and instant First Contentful Paint.
- Use React Server Components for data-fetching and static content
- Mark interactive islands with
'use client' - Stream large pages with
<Suspense>boundaries - Use
generateStaticParamsfor pre-rendering known routes at build time
Caching Strategies
TypeScript
1// TanStack Query — server state caching
2import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
4const queryClient = new QueryClient({
5 defaultOptions: {
6 queries: {
7 staleTime: 5 * 60 * 1000, // 5 minutes
8 gcTime: 30 * 60 * 1000, // 30 minutes
9 retry: 2,
10 },
11 },
12});
13
14// Nginx cache headers for static assets
15// Cache-Control: public, max-age=31536000, immutable (hashed filenames)
16// Cache-Control: no-cache (index.html)Performance Monitoring
TypeScript
1import { onLCP, onINP, onCLS } from 'web-vitals';
2import * as Sentry from '@sentry/react';
3
4function sendToAnalytics(metric: Metric) {
5 Sentry.metrics.distribution(metric.name, metric.value, {
6 tags: { page: window.location.pathname },
7 });
8}
9
10onLCP(sendToAnalytics); // Largest Contentful Paint < 2.5s
11onINP(sendToAnalytics); // Interaction to Next Paint < 200ms
12onCLS(sendToAnalytics); // Cumulative Layout Shift < 0.1