Server-Side Rendering With Next.js

Prateek Vijayvergiya
The Startup
Published in
5 min readOct 10, 2020
server side rendered components
Server Side Rendered Components

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 using Next.js
source — 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

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

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.

Now create a folder users inside pages folder, and fileindex.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 updatedpages/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 Userscomponent 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 ?

Thinking face

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

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.

--

--