DEV Community

Cover image for Server Side Rendering with Next.js
Prateek Vijayvergiya
Prateek Vijayvergiya

Posted on

Server Side Rendering with Next.js

Prerequisites

Basic understanding of React.js and Functional Programming Concepts.

Problem with Client Side rendering (CSR)

React, Angular and Vue are used to create Single Page Applications (SPAs). But they all provide CSR means whole application is rendered on client side by browser. So due to this, rendering of our initial page will take some time.

So to render our pages much faster we can use Next.js (Framework for React), which renders our pages on server side and give us pre-rendered HTML for our pages.

What is Server Side Rendering (SSR)

When a user request a webpage, server prepares the page by fetching user-specific data and sends it to the user’s machine. The browser then construes the content and displays the page. This entire process of fetching data from the database, creating an HTML page and serve it to user is known as SSR.

How Next.js helps in SSR

Next.js builds the HTML page at build time and serves the pre-rendered page from server to browser with minimal JavaScript code and when page is loaded by browser, its JavaScript code runs and makes the page fully interactive. (This Process is called Hydration)
Pre-rendering in Next.js

Two forms of pre-rendering

  1. Static Generation (SSG): HTML is generated at build time.
  2. Server Side Rendering: HTML is generated on each user request.

...

What are we going to build

A Next.js application with SSG which shows list of users. This is a new feature of Next.js which is available in Next 9.0 and later versions. You can check the application here. Complete source code can be found on Github.

So let’s build it.

Create a new Next.js app using ‘create-next-app’ which sets up working environment with everything ready for you.

npx create-next-app
or
yarn create next-app
Enter fullscreen mode Exit fullscreen mode

External Libraries

  1. Material-UI - as a UI library
  2. Dummy-Api for some data
  3. Axios for AJAX calls

Update your _app.js like this to change the header of application.

import React, {Fragment} from 'react'
import Head from 'next/head'
import '../styles/globals.css'
function MyApp({ Component, pageProps }) {
  return (
    <Fragment>
      <Head>
        <title>Go User</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Component {...pageProps} />
    </Fragment>
  )
}
export default MyApp
Enter fullscreen mode Exit fullscreen mode

Now create a lib folder at root of application and inside it create a file users.js. Inside it export an async function getAllUsers which will fetch list of users from Api.

So your lib/users.js will look like this

import axios from 'axios'
import {BASE_URL, APP_ID} from './constants'
export const getAllUsers = async () => {
  const users = await axios.get(
                `${BASE_URL}/user`,{headers:{'app-id': APP_ID}}
              )
  .then(({data}) => {
    return data
  })
  return users
}
Enter fullscreen mode Exit fullscreen mode

Here BASE_URL will be ‘https://dummyapi.io/data/api' and you can get the unique APP_ID from Dummy-Api.

Now create a folder users inside pages folder, and file index.js inside it.

Info: Any folder or file inside pages folder will become a webpage automatically, so now you can access this page at path /users

Let’s create an async function getStaticProps which provides props to the component on server side in pages/users/index.js. This function will call our getAllUsers and provide the list of users to the component to render.

Note: Everything inside getStaticProps will run on server.

export const getStaticProps = async () => {
  const allUsers = await getAllUsers()
  return {
    props: {
      allUsers
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now create a component which will render a card with individual user’s information provided to it as props.

At root folder create components/card/index.js and it will look like this

import React from 'react'
import { makeStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardActionArea from '@material-ui/core/CardActionArea'
import CardContent from '@material-ui/core/CardContent'
import CardMedia from '@material-ui/core/CardMedia'
import Typography from '@material-ui/core/Typography'
import styles from '../../styles/Card.module.css'
const UserCard = ({name, email, id, image}) => {
  const classes = useStyles()
  return (
    <Card className={styles.root}>
      <CardActionArea>
        <CardMedia
          component="img"
          alt="user image"
          height="200"
          image={image}
        />
        <CardContent>
          <Typography className={classes.text} gutterBottom
            variant="h5" component="h2">
            {name}
          </Typography>
          <Typography className={classes.text} variant="body2"
            color="textSecondary">
            {email}
          </Typography>
        </CardContent>
      </CardActionArea>
    </Card>
  )
}
const useStyles = makeStyles({
  root: {
    maxWidth: 250,
    padding: 5
  },
  text: {
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    overflow: 'hidden',
  }
})
export default UserCard
Enter fullscreen mode Exit fullscreen mode

Create a component Users which will call our card component with user data. so updated pages/users/index.js file look like this

import React from 'react'
import Grid from '@material-ui/core/Grid'
import { getAllUsers } from '../../lib/users'
import UserCard from '../../components/card'
const Users = ({allUsers}) => {
  return (
    <Grid container spacing={5} justify="space-evenly">
      {allUsers.data.map(({id, firstName, email, picture}) => (
        <Grid item xs={6} lg={2} md={4} key={id}>
          <UserCard {...{name: firstName, id, email, image: 
             picture}}/>
        </Grid>
       ))}
     </Grid>
  )
}
export const getStaticProps = async () => {
  const allUsers = await getAllUsers()
  return {
    props: {
      allUsers
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Here getStaticProps fetch the list of users from Api on server side and pass them to Users component as props. Then the whole component gets build on server itself and users data will be passed as json file.

Now build your application using yarn dev and check out application at http://localhost:3000/users

It will look like this

List of Users

...

Is Next.js actually Building the application on server ?

Alt Text

Modify the scripts object in package.json

"scripts": {
  "build": "next build && next export"
}
Enter fullscreen mode Exit fullscreen mode

Now run yarn build

You can actually see the pre rendered HTML pages on server inside the .next/server/pages

Alt Text

Summary

We made a Next.js application and rendered list of users on server side. Pre-rendered HTML pages comes up for each page on browser. You can check out more about Next.js here.

Top comments (2)

Collapse
 
maorkavod profile image
maorkavod • Edited

Im strongly recommend the everyone to use after.js.

github.com/jaredpalmer/after.js

and not nextJS,
nextjs is total overkill for most websites, 5 min with afterjs and you could have ssr spa working web app.

Collapse
 
malaniuk profile image
malaniuk

Thank you for using dummyapi 🙂