Server Side Rendering with Next.js
Tags: javascript, react, nextjs
Published: 2020-10-11 09:44:58

# 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](https://dev-to-uploads.s3.amazonaws.com/i/i8fxcroh8idof191d3cl.png)

# 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](https://go-user-five.vercel.app/users). Complete source code can be found on [Github](https://github.com/prateekvijayvergiya/go-user).

# 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
```

# External Libraries
1. [Material-UI](https://material-ui.com/) - as a UI library
2. [Dummy-Api](https://dummyapi.io/) 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
```
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
}
```
Here `BASE_URL` will be `‘https://dummyapi.io/data/api'` and you can get the unique `APP_ID` from [Dummy-Api](https://dummyapi.io/).

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
    }
  }
}
```

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
```

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
    }
  }
}
```

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](https://dev-to-uploads.s3.amazonaws.com/i/z8odtskh2ahp87p60o74.PNG)

...

# Is Next.js actually Building the application on server ?

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yuijmis2tbdgnh8q388a.jpg)

Modify the scripts object in `package.json`
```
"scripts": {
  "build": "next build && next export"
}
```

Now run `yarn build`

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

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yzlkdm7lflphwdya8wrx.png)

# 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](https://nextjs.org/).