Server-Side Rendering

Learn about server-side rendering and how to use it in a Next.js application.

Server-side rendering

As we discussed earlier, server-side rendering is a form of pre-rendering in which the HTML of a page is generated for the user’s request on the server before it’s served to the user. However, in the case of Jamstack applications, server-side rendering is not recommended. Even though it comes with its own set of advantages, server-side rendering also comes with a few drawbacks that affect the core principle of Jamstack. One of these drawbacks is that the web page would not be prebuilt and available to be served as soon as the request is made, going against the principles of a Jamstack application.

This way, the page’s HTML is generated for every request based on the request data, and the rendered page is sent to the client. On the client-side, React uses JavaScript instructions and JSON data from the server to add interactivity.

How to render a page on the server

Next.js provides an out-of-the-box asynchronous function getServerSideProps(). We can use it for server-side rendering, which the Next.js compiler will look for. Much like the getStaticProps() method for static generation, it’s exported from the page along with the page HTML, and the page is generated on the server when the application is built using the next build command.

Using the getServerSideProps() function

To demonstrate the usage of getServerSideProps(), let’s take the “Lookup a single random meal” endpoint of our API. We’ll create a new page called random-meal.js in our application that we’ll use for this.

import { Grid, Card, Typography } from '@mui/material';
import React from 'react'
import Image from 'next/image';
import styles from '../styles/Home.module.css'
import { useRouter } from 'next/router';

const MealCard = (props) => {
    const {meals} = props
    const router = useRouter();

    return (
        <Grid container direction="row" alignItems="center" justifyContent="center" spacing={1} sx = {{flex: "wrap"}}>
        {
          meals.map((meal) => 
            <Grid item key={meal.idMeal} 
            onClick = {() => router.push(`/meals/${meal.idMeal}`)}
            >
              <Card variant='outlined' className={styles.card}>
                <Grid container direction='column' justifyContent='center' alignItems='center' >
                  <Grid item 
                    className={styles.imgContainer}
                  >
                    <Image 
                      src = {meal.strMealThumb} 
                      alt={meal.strMeal} 
                      layout="fill"
                      objectFit="cover"
                      quality={100}
                    />
                  </Grid>
                  <Grid item>
                    <Typography variant='body1'>
                      {meal.strMeal}
                    </Typography>
                  </Grid>
                </Grid>
              </Card>
            </Grid>
          )
        }
      </Grid>
    )
}

export default MealCard;
Using the getServerSideProps() function in an application

The getServerSideProps() function can be seen in line 82 of our /pages/random-meal.js file. Similar to static generation, we also need to return the props object, which in our case, is meal. Those props are sent to the page as its properties and can then be used in the HTML of that page.

Note: When the page loads, it takes a while to load the data, which is a drawback of server-side rendering.

We also have a Button element, which reloads the page when the element clicked, so that the server-side rendering can be seen. However, reloading the page with user interactions isn’t a recommended practice and should be avoided. The only purpose of that is to see how server-side rendering works.