Server-Side Rendering With Next.JS

Server-Side Rendering With Next.JS

Building fast and scalable web applications with Next.JS server-side rendering capabilities

From faster initial load times to improved SEO and better user experience, Server side rendering (or SSR) has become one of the most favoured features of modern websites as you will soon see.

But what is server-side rendering, and why is it so important?

What Is Server Side Rendering?

Server-side rendering (SSR) is a well-known technique for enhancing the performance and user experience of web applications. In essence, it renders HTML pages on the server and sends them to the client, instead of having the client’s browser render them.

Think of it like a chef preparing a dish in advance before serving it to you.

When you order a dish at a restaurant, the chef doesn't start cooking it from scratch right when you order. Instead, the chef has already prepared the dish ahead of time, making it ready to be served as soon as you order it.

Similarly, with server-side rendering, the server prepares the web page content ahead of time and sends it to the browser as soon as the user requests the page (as opposed to client-side rendering, where the content of the web page is not available until after its JavaScript code has executed and retrieved the data from the server.)

This means that the browser can start displaying the content right away, without having to wait for the server to generate and send the content.

This approach can help improve the initial page load time, increase SEO, and improve accessibility.

What Is Next.JS

Next.js has grown to become one of the most popular frameworks for implementing SSR in React-based applications.

With Next.js, website features (like routing, code splitting, static site generation and of course, server-side rendering) that one would most likely need third-party frameworks to implement are already taken care of, right out of the box.

How Does Next.JS Handle Server-Side Rendering?

To understand why Next.js is so amazing, it may be important to fully understand how it handles server-side rendering.

Let's consider an example, shall we?

Suppose you have a React application that fetches data from an API and displays it in a table on a webpage. If you were to implement this using client-side rendering, the initial page load would be slower because the browser would need to download the JavaScript code, render the page, and then fetch the data from the API.

You’d agree that this is quite tedious with plain old React.

With Next.js and server-side rendering, however, the server would render the HTML for the table, including the data fetched from the API, and send it to the client. This means that the client would receive a fully rendered HTML page, which would be faster to load and display to the user.

Another important feature of this amazing framework is that:

Next.js, SEO And Site Accessibility

One of the key benefits of server-side rendering is improved SEO. Search engines can better index pages that are fully rendered on the server, which can lead to higher rankings and more traffic.

To further drive the point home, server-side rendering can improve accessibility for users with slow or unreliable internet connections, as well as those who rely on assistive technologies to navigate the web.

Next.js simplifies the process of implementing server-side rendering in React projects.

It even provides a variety of features that make it easy to fetch data, handle routing, and optimize performance.

For example, the getServerSideProps() function allows you to fetch data from an API and pass it to a React component at runtime, while the dynamic imports feature enables you to split your code into smaller, more manageable chunks that can be loaded on demand.

Don’t worry, we’ll take some code examples in due time.

Implementing Server-side rendering with Next.js

Now that we've discussed the benefits of server-side rendering and how it works, let's dive into how to implement it with Next.js.

Next.js provides two primary functions for server-side rendering:

  • getServerSideProps()

  • getStaticProps().

These functions allow you to fetch data at runtime or build time and pass it to your React components for rendering.

But more on that soon. Let’s set up our environment first.

Setting Up A Next.JS Project

To get started with Next.js you can follow these steps:

  • Ensure that you have Node.js and npm (or yarn) installed on your computer. You can download Node.js from the official website

  • Open your terminal or command prompt and navigate to the directory where you want to create your Next.js project.

  • Run the following command to create a new Next.js project using the official template:

npx create-next-app@latest

# or

yarn create next-app

# or

pnpm create next-app

You will be asked for the name of your project, and then whether you want to create a TypeScript project:

Would you like to use TypeScript with this project? … No / Yes

  • Give your project a name. In this case, we’ll call ours “my-app”. Call yours “potato salad” or whatever you’d like.

  • Select Yes to install the necessary types/dependencies and create a new JS/TS project.

  • Wait for the installation process to complete. This may take a few minutes, as Next.js installs all the necessary dependencies for your project.

  • Once the installation is complete, navigate to your project directory:

cd my-app

In the terminal, start a Next.js project by running

npm run dev

#or

yarn dev

  • This should spin up a Next.js project for you in a few minutes, and point it to http://localhost:3000/

  • Open your browser and open this address

  • You should see a next.js project template, ready to be edited.

Installation To Server Side Rendering

Now that you have successfully installed Next.js, here’s where to go from there.

  • Feel free to delete the public/favicon.ico and public/vercel.svg files.

  • Remove the contents of the pages/api folder. We don’t need any API routes for this project.

  • In the pages folder, remove the pages/api file.

  • Open the pages/index.js file and delete everything in it.

  • Delete the styles folder, as we'll be using inline styles for this guide.

Setting up our dummy project

Navigate to the pages directory and open the pages/index.js file.

Add the following code to the file:

import { useEffect, useState } from "react";

function Home({ posts }) {

  const [loading, setLoading] = useState(true);

  useEffect(() => {

    setLoading(false);

  }, []);

  if (loading) {

    return <p>Loading...</p>;

  }

  return (

    <>

      <h1>Latest Posts:</h1>

      {posts.map((post) => (

        <div key={post.id}>

          <h2>{post.title}</h2>

          <p>{post.body}</p>

        </div>

      ))}

    </>

  );

}

export async function getServerSideProps() {

  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  const posts = await res.json();

  return {

    props: {

      posts,

    },

  };

}

export default Home;

Let’s walk through the code step by step, shall we?

1. Importing the necessary modules and components:

import { useEffect, useState } from "react";

Here, we are importing the useEffect and useState hooks from React.

2. Defining the component that will be rendered:

function Home({ posts }) {

  const [loading, setLoading] = useState(true);

  useEffect(() => {

    setLoading(false);

  }, []);

  if (loading) {

    return <p>Loading...</p>;

  }

  return (

    <>

      <h1>Latest Posts:</h1>

      {posts.map((post) => (

        <div key={post.id}>

          <h2>{post.title}</h2>

          <p>{post.body}</p>

        </div>

      ))}

    </>

  );

}
  • Here, we are defining the Home component that takes posts as a prop.

  • The component renders a list of posts with their titles and bodies. We are using the useState hook to set the initial state of the loading variable to true.

  • Then, we are using the useEffect hook to set loading to false once the component is mounted.

  • This helps us display a "Loading..." message until the data is fetched and ready to be displayed.

3. Exporting the component and enabling server-side rendering:

export async function getServerSideProps() {

  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  const posts = await res.json();

  return {

    props: {

      posts,

    },

  };

}

export default Home;
  • Here, we are exporting the Home component as the default export, and also defining the getServerSideProps function.

  • This function is used by Next.js to fetch data from a remote data source and return it as props to the component.

  • In this case, we are fetching data from the JSONPlaceholder API and returning the posts array as props.

  • When the page is loaded, the getServerSideProps function is called, and the fetched data is passed to the component as props.

  • The component then renders the list of posts with their titles and bodies.

And that's it! With this code, we have set up a simple Next.js app that fetches data from an external API and displays it on the page using server-side rendering.

4. Run the development server with npm run dev.

Navigate to localhost:3000 to see the rendered page.

Congratulations! You've successfully implemented server-side rendering with Next.js.

getServerSIdeProps() versus getStaticProps()

getServerSideProps() and getStaticProps() are both very important methods in Next.js that allow you to fetch data at build time or runtime, respectively.

However, it is important to realize that there is a difference between both, depending on your project’s needs.

getServerSideProps()

This function is used to fetch data at runtime, meaning that the data is fetched every time the page is requested.

But why is this important?

Well, assume you have dynamic data that changes frequently and needs to be updated on every page request. This function might come in handy and is just the tool for the job.

For example, if you have a news website and you want to show the latest news on your homepage, you would use getServerSideProps() to fetch the latest news from your server.

Consider this example

export async function getServerSideProps() {

  const res = await fetch('https://api.example.com/data');

  const data = await res.json();

  return {

    props: {

      data

    }

  }

}

Just like ordering food at a restaurant when you’re ready to eat, the getServerSideProps() function fetches data from an API at runtime (i.e., when the page is requested) and returns it as a prop to the component that is being rendered.

getStaticProps()

This function, on the other hand, is used to fetch data at build time, which means that the data is fetched once during the build process and then cached. This is useful when you have data that doesn't change frequently and you don't want to fetch it every time a user requests the page.

For example, if you have a blog website and you want to show a list of your blog posts on your homepage, you would use getStaticProps() to fetch the list of posts at build time.

Consider this code example:

export async function getStaticProps() {

  const res = await fetch('https://api.example.com/data');

  const data = await res.json();

  return {

    props: {

      data

    }

  }

}

Like a restaurant chef preparing a meal hours before you arrive, the getStaticProps() function fetches data from an API at build time (i.e., when you run the build command for your Next.js app) and returns it as a prop to the component that is being rendered.

So, when a user requests the page, the data is already there and can be served instantly without needing to make an API call.

In general, you should use getServerSideProps() when you have data that changes frequently and getStaticProps() when you have data that doesn't change frequently.

Best Practices for Implementing SSR with Next.js

When implementing server-side rendering with Next.js, there are several best practices to follow to ensure that your application performs well and provides a great user experience.

Here are a few of them:

  1. Use server-side rendering selectively

  2. Optimize your images and other assets:

  3. Use caching

  4. Use dynamic imports

  5. Minimize the use of third-party libraries

  6. Optimize your projects for mobile devices

  7. Test them thoroughly

Conclusion

In conclusion, by using Next.js instead of third-party libraries that bloat up your package files for your SSR needs, you can improve the performance and SEO of your React applications, while also ensuring a smooth and fast user experience for your visitors.