Back to blog

Performance Optimization in React and Next.js

Performance Optimization in React and Next.js

Creating ultra-fast React applications is not just about writing good code. It requires deeply understanding how React works, how Next.js optimizes your application, and what strategies you can apply to maximize performance.

Core Web Vitals: The New Success Metric

Google has established Core Web Vitals as key metrics for measuring user experience. For React and Next.js applications, this means specifically optimizing:

  • LCP (Largest Contentful Paint): The largest content element must load in less than 2.5 seconds
  • FID (First Input Delay): The initial interaction must respond in less than 100ms
  • CLS (Cumulative Layout Shift): Elements should not move unexpectedly during loading

1. React Component Optimization

React.memo for Pure Components

One of the most effective patterns is wrapping components that don't need to re-render with every parent change:

const MemoizedComponent = React.memo(({ data }) => {
  return <div>{data}</div>;
});

useMemo and useCallback

Avoid expensive calculations and function recreation on every render:

  • useMemo: To memorize expensive calculated values
  • useCallback: To memorize functions passed as props

Code Splitting with lazy and Suspense

Load components only when they are needed:

const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <HeavyComponent />
    </Suspense>
  );
}

2. Next.js Specific Strategies

Image Optimization

The Next.js Image component automatically optimizes images:

  • Lazy loading by default
  • Automatic resizing based on device
  • Modern formats (WebP, AVIF) with fallback
  • Blur placeholder for better UX

Static Site Generation (SSG)

For content that doesn't change frequently, use getStaticProps to pre-render pages at build time. This completely eliminates server time on every request.

Incremental Static Regeneration (ISR)

Combines the benefits of SSG with the ability to update content:

export async function getStaticProps() {
  return {
    props: { data },
    revalidate: 60 // Regenerates every 60 seconds
  };
}

3. Dependency Optimization

Bundle Size Analysis

Use tools like webpack-bundle-analyzer to identify heavy dependencies:

  • Remove unused dependencies
  • Use lighter alternatives when possible
  • Implement tree shaking correctly

Dynamic Imports

Don't load everything at once. Dynamically import heavy libraries only when needed:

const handlePdfExport = async () => {
  const jsPDF = await import('jspdf');
  // Use jsPDF only when needed
};

4. State Optimization

Avoid Unnecessary Re-renders

Structure your state intelligently:

  • Place state as close as possible to where it is used
  • Split large states into smaller, specific states
  • Use Context API sparingly (can cause massive re-renders)

Zustand or Jotai for Global State

Lighter and more performant alternatives to Redux:

  • Smaller bundle size
  • Simpler API
  • More optimized re-renders

5. Server Performance

API Routes Optimization

Next.js API routes must be fast:

  • Implement caching with Redis or similar
  • Use persistent database connections
  • Compress responses (gzip)
  • Implement rate limiting

Edge Functions

For simple but frequent operations, consider using Edge Functions that run closer to the user.

6. Measurement and Monitoring

Web Vitals Tracking

Next.js includes native support for measuring Web Vitals. Implement tracking in _app.js:

export function reportWebVitals(metric) {
  // Send to your analytics service
  console.log(metric);
}

Lighthouse CI

Automate performance audits in your CI/CD pipeline to detect regressions before production.

7. Additional Best Practices

  • Prefetching: Next.js automatically prefetches visible links
  • Font optimization: Use next/font to optimize fonts
  • Avoid layout shift: Define explicit dimensions for dynamic elements
  • Streaming SSR: In React 18+ and Next.js 13+, use Suspense for streaming
  • Parallel data fetching: Don't make sequential requests when you can make them in parallel

Conclusion

Performance optimization is an ongoing process. It's not something you do once and forget. It requires:

  • Constant metric measurement
  • Testing on real devices and slow networks
  • Periodic review of dependencies and code
  • Staying updated with new React and Next.js features

By implementing these techniques, you can create applications that not only feel fast but also improve your SEO, user conversion, and overall satisfaction.

At Brixato, performance is a priority from day one of every project. We don't wait for users to complain about slowness; we build optimized applications from the start.