Taking advantage of Static & Dynamic Pages in Next.js

Next.js has emerged as one of the most popular frameworks for building React-based applications, especially when it comes to enhancing performance and scalability. Its unique approach to rendering pages allows developers to take full advantage of both static and dynamic content. This post will explore the benefits and use cases of static and dynamic pages in Next.js, helping you make informed decisions when building your next application.

Understanding Static and Dynamic Pages

Before diving into Next.js, it's essential to define what we mean by static and dynamic pages.

  • Static Pages: These pages are generated at build time and served as static HTML files. They are beneficial for content that does not change frequently, such as blog posts, documentation, or product listings. Static pages are fast and improve SEO performance, as search engines can easily crawl the pre-rendered content.

  • Dynamic Pages: In contrast, dynamic pages are generated at request time. They are suited for content that frequently changes or is user-specific, such as user dashboards, shopping cart contents, or any data fetched from a database. Dynamic pages are built using server-side rendering (SSR) or client-side rendering (CSR), allowing for a more personalized experience.

The Power of Next.js: Static and Dynamic Rendering

Next.js offers multiple rendering strategies to cater to both static and dynamic use cases, empowering developers to build highly performant applications. Below are the primary methods for handling static and dynamic pages:

Static Generation (SG)

With Next.js, static generation can be achieved through the getStaticProps and getStaticPaths functions, allowing developers to pre-render pages at build time.

Use Cases for Static Generation

  • Blog Posts: If you're building a blog, each post can be generated as a static page, optimizing load times and SEO.

  • Product Listings: E-commerce sites can generate static product pages that don't change frequently.

  • Marketing Pages: Landing pages with consistent content can be pre-rendered to ensure instant loading for visitors.

Implementation Example

Here's a simple example of how to implement static generation for a blog post:

// pages/posts/[id].js

import { useRouter } from 'next/router';

const Post = ({ post }) => {
  const router = useRouter();

  // Fallback for server-side rendering
  if (router.isFallback) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
};

export async function getStaticPaths() {
  // Fetch list of posts for generating paths
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }));

  return { paths, fallback: true };
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await res.json();

  return {
    props: {
      post,
    },
  };
}

export default Post;

Server-Side Rendering (SSR)

For use cases where content needs to be fetched based on each request, Next.js provides server-side rendering using the getServerSideProps function. This method ensures users always receive the most up-to-date content.

Use Cases for Server-Side Rendering

  • User Profiles: Fetch user-specific data that must be up-to-date with every request.

  • Dashboards: Render protected or user-specific data using SSR for security and accuracy.

  • E-commerce Cart Handling: Ensure that cart information reflects the latest updates and changes.

Implementation Example

Here's an example of using SSR for a user dashboard:

// pages/dashboard.js

const Dashboard = ({ user }) => {
  return (
    <div>
      <h1>Welcome, {user.name}</h1>
      <p>Your email: {user.email}</p>
    </div>
  );
};

export async function getServerSideProps(context) {
  const res = await fetch(`https://api.example.com/user/${context.query.id}`);
  const user = await res.json();

  return {
    props: {
      user,
    },
  };
}

export default Dashboard;

Client-Side Rendering (CSR)

For content that can be rendered client-side, Next.js also allows developers to use React's built-in state management and lifecycle methods. Client-side rendering is reasonable for pages that do not need to be indexed by search engines or require real-time data updates.

Use Cases for Client-Side Rendering

  • Real-Time Chat Applications: Data updates can be handled on the client side without requiring a full page refresh.

  • User Interactions: Components that interact with user input and don’t require immediate server interaction.

Implementation Example

// pages/chat.js

import { useEffect, useState } from 'react';

const Chat = () => {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const fetchMessages = async () => {
      const res = await fetch('https://api.example.com/chat/messages');
      const data = await res.json();
      setMessages(data);
    };

    fetchMessages();
  }, []);

  return (
    <div>
      <h1>Chat Messages</h1>
      <ul>
        {messages.map((msg) => (
          <li key={msg.id}>{msg.text}</li>
        ))}
      </ul>
    </div>
  );
};

export default Chat;

Combining Multiple Rendering Strategies

Next.js gives you the flexibility to mix and match static and dynamic rendering strategies in one application. Depending on your specific use case, you may find that a combination is the best solution. For instance, a blog may leverage static generation for individual posts while using SSR for the homepage that displays the results of a search query.

Conclusion

Static and dynamic pages represent two sides of the same coin in Next.js, each offering unique advantages suited to different requirements. By effectively leveraging static generation, server-side rendering, and client-side rendering, you can create fast, responsive, and SEO-friendly applications that cater to a wide array of user needs.

To get started, explore the official Next.js documentation for more examples and in-depth explanations of these concepts. Understanding when and how to use each rendering strategy will empower you to build high-performance applications tailored to your audience's needs. Happy coding!

31SaaS

NextJs 14 boilerplate to build sleek and modern SaaS.

Bring your vision to life quickly and efficiently.