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)
Two forms of pre-rendering
- Static Generation (SSG): HTML is generated at build time.
- 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
- Material-UI - as a UI library
- Dummy-Api for some data
- 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 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
...
Is Next.js actually Building the application on server ?
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.
Top comments (2)
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.
Thank you for using dummyapi 🙂