We've all been there — your Next.js app is working fine in development, but the moment it hits production, it feels like it's running on a potato.

Slow page loads, unresponsive UI, and Core Web Vitals screaming at you like an angry manager.

That was me a few months ago. But after testing, breaking, and optimizing my app to the max, I finally cracked the code. Here's exactly how I made my Next.js app load faster and how you can too.

None
Photo by Kelly

Spoiler: It's not just about adding "use client" everywhere.

Ditch Useless useEffect Calls 🚫

Let's talk about useEffect()—the go-to hammer for devs who see every problem as a nail.

I had components using useEffect() for things that could be done statically or with server-side rendering. Removing unnecessary useEffect calls instantly reduced my client-side JavaScript load.

The Wrong Way

None

This forces the client to fetch data after the page loads. Slow and unnecessary.

The Right Way (Server Components FTW)

None

No useEffect(), no state management, just pure server-side rendering (SSR). The page loads with data pre-fetched.

Use Image Optimization (next/image) 📷

If you're still using <img> tags like it's 2010, you're missing out.

I had multiple large images slowing down my page. Switching to Next.js's next/image reduced my Largest Contentful Paint (LCP) time significantly.

The Old Way (Bad Performance)

None

This loads the full image, even if the user is on a small screen. Wasteful.

The Next.js Way

None

This automatically: ✔ Optimizes image sizeServes WebP format when possibleLazy-loads non-critical images

Instant speed boost.

Reduce JavaScript (Move Logic to the Server)

Every extra KB of JavaScript adds execution time on the client. The trick? Offload work to the backend or Edge functions.

I used to process data on the client, which was dumb because the same logic could run on the server before sending the response.

Bad: Processing on the Client

None

This means fetching everything first, then filtering on the client. Unnecessary load.

Good: Processing on the Server

None

Now, only relevant data reaches the client.

Less JavaScript = faster rendering.

Use Static Generation Where Possible (getStaticProps) 🌎

If your data doesn't change often, don't fetch it dynamically. Instead, pre-generate pages at build time using getStaticProps().

export async function getStaticProps() {
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();

  return { props: { posts }, revalidate: 60 }; // Refresh every 60s
}

export default function Blog({ posts }) {
  return <div>{posts.map((p) => <p key={p.id}>{p.title}</p>)}</div>;
}

This generates HTML ahead of time, meaning zero wait time when users visit the page.

Optimize Fonts & Reduce CLS (Cumulative Layout Shift) 🎨

Google hates layout shifts. If your fonts load late, users will see a "flash of invisible text" (FOIT).

I fixed this by: ⭐ Using system fonts (sans-serif, serif) ⭐ Preloading custom fonts ⭐ Setting font-display: swap

Example (Google Fonts Optimization)

None

This prevents text from "jumping" when fonts load. Smooth experience.

Enable Compression & Caching in next.config.js

I enabled Brotli and Gzip compression to reduce file size and speed up responses.

Example (Optimized next.config.js)

None

Caching = less network requests = faster page loads.

Before optimizations, my app loaded in 3.9 seconds (according to Lighthouse).

After these fixes, it dropped to 0.9 seconds.

🌔 No useEffect abuse 🌔Rerver-side data fetching 🌔ROptimized images & fonts 🌔R Less JavaScript, more static pages 🌔R Proper caching & compression

Result? A buttery smooth Next.js app that loads instantly.

Try these optimizations in your project. If you have any cool performance tricks, drop them in the comments!

Let's build faster, smarter apps.

Did this help? Share it so more devs stop making slow Next.js apps! 🏆