Home     /Articles     /

Optimizing Performance in Next.js 15 with the App Router

NextJS 15

Optimizing Performance in Next.js 15 with the App Router

Written by Briann     |

December 04, 2024     |

1.4k |

Next.js 15 introduces powerful optimizations for building modern, scalable applications, especially with the App Router. This architecture focuses on server components, improved caching, and routing flexibility, making it easier than ever to deliver blazing-fast applications. In this post, we’ll dive into key performance strategies and examples tailored for Next.js 15 with the App Router.





1. Use Server Components Where Possible

Server components in the App Router allow you to offload rendering to the server, reducing the client-side JavaScript bundle size and improving performance.


Example: A Server Component with Data Fetching

// app/page.js

export default async function Page() {
  const res = await fetch("https://api.example.com/posts", { cache: "force-cache" });

  const posts = await res.json();  return (
    <div>
      {posts.map((post) => (
        <h2 key={post.id}>{post.title}h2>
      ))}
    div>
  );
}

Using cache: "force-cache" ensures the response is cached for faster subsequent loads.





2. Optimize Data Fetching with the New fetch API

The App Router uses the built-in Fetch API, which provides improved control over caching and revalidation.


Example: On-demand Data Revalidation

// app/dashboard/page.js

// app/dashboard/page.js
export default async function Dashboard() {
  const res = await fetch("https://api.example.com/stats", {
    next: { revalidate: 10 }, // Revalidate every 10 seconds
  });

  const stats = await res.json();

  return (
     <div>
      <h1>Dashboard Statsh1>
      <p>Users: {stats.users}p>
      <p>Sales: {stats.sales}p>
    div>
 );
}





3. Prefetch Links Automatically

In Next.js 15, the App Router automatically prefetches links for pages that the user is likely to visit next. However, you can disable prefetching for specific links if needed.


Example:


// app/components/Navigation.js

import Link from "next/link";

export default function Navigation() {
  return (
    <nav>
      <Link href="/about" prefetch={false}>
        About Us
      Link>
      <Link href="/contact">
        Contact
      Link>
    nav>
  );
}





4. Leverage Image Component for Optimized Media

The next/image component has been enhanced in Next.js 15, making it even easier to handle images.


Example: Optimized Hero Image

// app/page.js

import Image from "next/image";

export default function HomePage() {
  return (
    <div>
      <Image
        src="/images/hero.jpg"
        alt="Hero Image"
        width={1200}
        height={800}
        priority
      />
    div>
  );
}


The priority attribute ensures the image loads quickly, improving perceived performance.





5. Reduce Client-side Code with Server-only Logic

By offloading logic to the server, you minimize the JavaScript sent to the browser.


Example: Server-only API Call

// app/profile/page.js

export default async function Profile() {
  const res = await fetch("https://api.example.com/profile", { cache: "no-store" });
  const profile = await res.json();

  return (
    <div>
      <h1>{profile.name}h1>
      <p>Email: {profile.email}p>
    div>
  );
}





6. Use Parallel and Sequential Data Fetching

With the App Router, you can fetch data in parallel or sequentially, depending on your requirements.


Example: Parallel Fetching

// app/products/page.js

export default async function ProductsPage() {
  const [categories, products] = await Promise.all([
    fetch("https://api.example.com/categories").then((res) => res.json()),
    fetch("https://api.example.com/products").then((res) => res.json()),
  ]);

  return (
    <div>
      <h1>Productsh1>
      <div>{categories.length} Categoriesdiv>
      <div>{products.length} Productsdiv>
    div>
  );
}





7. Use Middleware for Edge Caching

Middleware runs at the edge, enabling you to optimize requests before they hit your backend.


Example: Simple Middleware for Redirection

// middleware.js

import { NextResponse } from "next/server";

export function middleware(request) {
  const url = request.nextUrl.clone();
  if (url.pathname === "/old-page") {
    url.pathname = "/new-page";

    return NextResponse.redirect(url);
  }
}





8. Lazy Load Non-critical Components

For components that aren’t immediately visible, lazy loading helps reduce initial load time.


Example: Lazy Loading with React.lazy

// app/page.js

import dynamic from "next/dynamic";
const LazyComponent = dynamic(() => import("./components/LazyComponent"), { ssr: false });

export default function HomePage() {
  return (
    <div>
      <h1>Welcome to the Homepageh1>
      <LazyComponent />
    div>
  );
}





9. Optimize Metadata with the metadata API

Use the metadata API to define SEO-friendly and performant metadata directly in your components.


Example:

// app/layout.js

export const metadata = {
  title: "Optimized Page",
  description: "This is an optimized page in Next.js 15.",
};

export default function Layout({ children }) {
  return <>{children}>;
}





10. Monitor Web Vitals

Next.js 15 provides built-in support for monitoring web vitals to track and improve performance.


Example: Web Vitals Reporting

export function reportWebVitals(metric) {
  console.log(metric);
}






Conclusion

Optimizing performance in Next.js 15 is all about leveraging its modern features, such as server components, incremental revalidation, and the App Router’s enhanced data fetching capabilities. By applying these strategies, you can build highly performant and scalable applications.


What optimization techniques do you use with the Next.js App Router?

Powered by Froala Editor

Related Articles

What’s New with NextJs 15 RC

NextJS 15

What’s New with NextJs 15 RC

December 01, 2024