~/blog/react-nextjs-performance-tips
Published on

React and Next.js Performance Optimization Tips

802 words5 min read–––
Views
Authors
  • avatar
    Name
    Mohamed Adan
    Twitter

Performance is crucial for modern web applications. Users expect fast, responsive interfaces, and poor performance can lead to high bounce rates. In this post, I'll share practical optimization techniques I've learned while building React and Next.js applications.

Code Splitting with React.lazy

React.lazy allows you to load components only when they're needed, reducing your initial bundle size:

import React, { Suspense, lazy } from 'react'

const LazyComponent = lazy(() => import('./LazyComponent'))

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  )
}

Next.js Image Optimization

Next.js Image component automatically optimizes images:

import Image from 'next/image'

function MyComponent() {
  return (
    <Image
      src="/my-image.jpg"
      alt="Description"
      width={500}
      height={300}
      placeholder="blur"
      priority={false}
    />
  )
}

Benefits:

  • Automatic image optimization
  • Lazy loading by default
  • Responsive images
  • Modern formats (WebP, AVIF)

Memoization with useMemo and useCallback

Prevent unnecessary re-renders with React hooks:

import { useMemo, useCallback } from 'react'

function ExpensiveComponent({ data, onUpdate }) {
  const processedData = useMemo(() => {
    return data.map((item) => ({
      ...item,
      processed: complexCalculation(item),
    }))
  }, [data])

  const handleClick = useCallback(() => {
    onUpdate(processedData)
  }, [processedData, onUpdate])

  return <div onClick={handleClick}>{/* ... */}</div>
}

Static Site Generation (SSG) in Next.js

For pages with static content, use SSG for optimal performance:

// pages/blog/[slug].js
export async function getStaticPaths() {
  const posts = await getAllPosts()
  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }))

  return { paths, fallback: false }
}

export async function getStaticProps({ params }) {
  const post = await getPostBySlug(params.slug)
  return {
    props: { post },
    revalidate: 60, // ISR: revalidate every 60 seconds
  }
}

Bundle Analysis

Identify what's bloating your bundle:

npm install @next/bundle-analyzer
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer({
  // your config
})

Performance Monitoring

Use Web Vitals to track real user performance:

// pages/_app.js
export function reportWebVitals(metric) {
  if (metric.label === 'web-vital') {
    // Send to analytics
    console.log(metric)
  }
}

Key Takeaways

  1. Lazy load components to reduce initial bundle size
  2. Optimize images with Next.js Image component
  3. Memoize expensive calculations and callbacks
  4. Use SSG/ISR for static and semi-static content
  5. Analyze your bundle regularly
  6. Monitor performance with Web Vitals

These optimizations can significantly improve your application's performance and user experience. Start with the most impactful changes and measure the results.