kapsys-logo
Contact Us
Back

Under The Hood: How Next.js SSR Works

February 5, 2024 by Daria Andrieieva
  • User Experience
Next.js SSR

In the dynamic landscape of web development, staying ahead of the curve is crucial for delivering seamless user experiences. Server-side rendering (SSR) has emerged as a powerful technique, and Next.js SSR has become a go-to framework for implementing it efficiently. 
 

Join Kapsys as we explore the inner workings of Next.js SSR, exploring what SSR is, why it matters, and how Next.js takes it to the next level.

 

Sign up to our blog to stay tuned about the latest industry news.

Understanding Server-Side Rendering (SSR)

Server-side rendering (SSR) is a technique used to enhance the performance and SEO of web applications by rendering pages on the server before sending them to the client. Traditionally, web pages were rendered on the client side using JavaScript, which could lead to slower initial page loads and potential SEO challenges.
 

With Next.js SSR, the server dynamically generates the HTML content for a page, sending a fully rendered page to the client. This approach provides several benefits, which we'll discuss later in this article. 
 

Read: Hybrid Sites With Next.js: The Best Static And Server-Rendered Worlds, Deployed On Vercel

The Core Concept of Next.js SSR

Next.js, a React framework, streamlines the implementation of SSR. Let's explore the core concepts that make Next.js SSR stand out:

Pages and routes

In Next.js, each file within the pages directory corresponds to a route in the application. When a user navigates to a specific route, Next.js SSR identifies the corresponding file in the pages directory and renders the associated React component.

getServerSideProps

Next.js introduces a particular function, getServerSideProps, which enables Next.js SSR for specific pages. When implemented in a page component, this function runs on the server side during every request, allowing developers to fetch data and pass it as props to the page component.
 

// Example of getServerSideProps
export async function getServerSideProps(context) {
 // Fetch data from an external API
 const res = await fetch('https://api.example.com/data');
 const data = await res.json();

 // Return the data as props
 return {
 props: {
 data,
 },
 };
}

Server-side rendering lifecycle

When a user makes a request to a page with SSR enabled, Next.js follows a specific lifecycle:

  • The server executes the getServerSideProps function, fetching data and passing it as props to the page component.
     

  • Next.js renders the page with the received data, creating a fully rendered HTML page.
     

  • The server sends the HTML page to the client, which can be displayed immediately.

This process ensures the user receives a fully rendered page directly from the server, minimizing client-side rendering and providing a faster initial loading experience.

Automatic code splitting

Next.js leverages automatic code splitting to optimize performance. Only the requested page's necessary JavaScript and CSS code are sent to the client, reducing the initial load time. This is achieved by creating separate bundles for each page, ensuring that users download only the code they need.

Client-side navigation

Next.js SSR  complements fast initial page loads with client-side navigation. Subsequent navigation within the application is handled on the client side, providing a smooth and responsive user experience. This hybrid approach combines the benefits of Next.js SSR and client-side rendering, offering the best of both worlds.
 

Also Read: The Difference Between React And Nextjs: How They Compare?

Next.js

Benefits of Next.js SSR

Let's take a closer look and discuss why Next.js SSR matters: 

Improved SEO

Search engines prefer pages with content readily available in the HTML markup. Next.js SSR ensures that search engine crawlers receive fully rendered pages, enhancing the visibility of the application in search results.
 

Read: Next.js SEO: Search Engine Visibility For Next.js Sites With Content From Strapi or Kontent.ai

Performance optimization

Next.js SSR significantly reduces the time it takes for users to see the initial content of a page. The perceived performance is improved by rendering pages on the server and sending pre-rendered HTML to the client.

Accessibility and progressive enhancement

Next.js SSR ensures that the essential content of a page is accessible to users, even if their browsers have limited JavaScript capabilities. This approach aligns with the principles of progressive enhancement, providing a baseline experience for all users and enhancing it for those with more capable browsers.
 

Read: Top 10 Features Of Next js

How to Implement Next.js SSR: Step-by-step Instructions

Creating a Next.js application with Server-Side Rendering (SSR) involves a step-by-step process. Below is a comprehensive guide to help you implement Next.js SSR effectively:

Step 1: Set up a Next.js project

Here's how you can set up your first Next.js project: 

  • Create a Next.js App

Open your terminal and run the following command to create a new Next.js app:
 

npx create-next-app my-ssr-app
Replace my-ssr-app with your preferred project name.
Navigate to Your Project
Move into the project directory:

cd my-ssr-app


Read: Next.js Basic Tutorial: Unveiling the Power of Next.js

Step 2: Create a Next.js SSR page

Now, to create a Next.js SSR page, use the following instructions:

  • Create a New Page

In the pages directory, create a new file for your SSR page. For example, create pages/ssrPage.js.

  • Implement getServerSideProps

In the new file, use the getServerSideProps function to fetch data and pass it as props to the page component.
 

// pages/ssrPage.js
import React from 'react';

const SsrPage = ({ data }) => {
 return (
 <div>
 <h1>Server-Side Rendered Page</h1>
 <p>Data: {data}</p>
 </div>
 );
};

export async function getServerSideProps() {
 // Fetch data from an API
 const res = await fetch('https://api.example.com/data');
 const data = await res.json();

 // Return data as props
 return {
 props: {
 data,
 },
 };
}

export default SsrPage;

Step 3: Run your Next.js Aapp

To run your app, you need to: 

  • Start the development server

Run the following command to start your Next.js app:
 

npm run dev


This will start the development server, and you can access your app at http://localhost:3000.

  • Visit your Next.js SSR page

Open your browser and navigate to http://localhost:3000/ssrPage (or whatever route you created). You should see your server-side rendered page with data fetched from the API.

Step 4: Client-side navigation (Optional step)

If you want to implement client-side navigation between pages, you can use the link component provided by Next.js.

  • Create Another Page

Create another page in the pages directory, for example, pages/clientSidePage.js.

  • Implement the page component

Implement the component and use the Link component for navigation:
 

// pages/clientSidePage.js
import React from 'react';
import Link from 'next/link';

const ClientSidePage = () => {
 return (
 <div>
 <h1>Client-Side Rendered Page</h1>
 <Link href="/ssrPage">
 <a>Go to SSR Page</a>
 </Link>
 </div>
 );
};

export default ClientSidePage;
  • Run your Next.js app

Restart your development server if needed and navigate to http://localhost:3000/clientSidePage. You should be able to navigate between the Next.js SSR page and the client-side rendered page.

Step 5: Deployment

When you're ready to deploy your Next.js SSR app, follow the deployment instructions provided by your chosen hosting platform. Popular options include VercelNetlify, and AWS.
 

That's it! You've successfully created a Next.js app with Server-Side Rendering and optional client-side navigation. Feel free to customize and expand based on your project requirements.
 

Read: Why Next.js is a Game Changer for React Developers

server side rendering

Best Practises for Next.js SSR

Here are five of the most essential best practices for implementing Next.js SSR:

Optimize API requests

Efficiently manage API requests for enhanced Next.js SSR performance and user experience:

  • Batching Requests: Group multiple data requests into a single API call to reduce the number of server round-trips, minimize latency, and improve page load times.
     

  • Use CDN for Static Assets: Leverage Content Delivery Networks (CDNs) to serve static assets, such as images and stylesheets, from edge locations closer to users. This reduces latency and accelerates content delivery for improved performance.

Leverage incremental static regeneration (ISR)

Next.js SSR provides Incremental Static Regeneration, a feature that allows you to update static pages without rebuilding the entire site. Key practices include:

  • Revalidate Option: Set the revalidate option in getStaticProps to determine how frequently a page should be regenerated. This ensures that your static pages stay up-to-date without compromising performance.
     

  • Partial Static Generation: Utilize ISR for pages that can be partially static, providing a balance between dynamic and static content.

Handle errors gracefully

Implement proper error handling within the getServerSideProps function to ensure a graceful user experience:

  • Error Components: Design error components to provide meaningful error messages to users, guiding them on what went wrong during data fetching.
     

  • Logging: Implement logging mechanisms to track errors on the server side, facilitating debugging and troubleshooting.

Optimize component rendering

Efficiently manage component rendering to enhance Next.js SSR performance:

  • Memoization: Utilize memorization techniques, such as React's memo or useMemo, to prevent unnecessary re-rendering of components, optimizing resource usage.
     

  • Minimize Component Complexity: Break down complex components into smaller, manageable pieces. This improves Next.js SSR performance and makes code maintenance and debugging more straightforward.

Implement loading states and skeleton screens

Enhance user experience during data fetching by implementing loading states and skeleton screens:

  • Loading States: Communicate to users when data is fetched on the server by incorporating loading states within your components. This mitigates user frustration and provides feedback during the wait.
     

  • Skeleton Screens: Consider using skeleton screens or placeholders while waiting for data to maintain the layout structure. This visually informs users that content is loading, creating a smoother perceived performance.

These best practices ensure that your Next.js SSR application is performant and provides a reliable and seamless user experience. 
 

Read: Why Choose Next.js for Your Next Web Project?

what is server-side rendering

Conclusion 

Understanding the inner workings of Next.js SSR is crucial for optimizing web applications, improving performance, and ensuring a positive user experience. 

As the web development landscape evolves, frameworks like Next.js are pivotal in simplifying complex concepts and making them accessible to developers of all levels. 

Incorporating SSR into your Next.js applications is not just a best practice—it's a strategic move towards building faster, more accessible, and search engine-friendly web applications.
 

Keep up with Kapsys to learn all about Next.js and more!