Optimise your NextJS Web Application for SEO

By Domnic Amalan On September 27 2021

In React world everything is rendered in client-side, so when the crawlers try to crawl your site, there will be no content for them to rank. This is bad in terms of SEO.

Table of contents

  1. How browsers, crawlers and social media platform detect your SEO meta tags
  2. How is react component rendered in terms of SEO
  3. How NextJS solves the biggest problem of react?
  4. What are methods you can render these pages for better SEO optimisation.

How do browsers, crawlers and social media platform detect your SEO meta tags?

There are two types of rendering in the web world:

  1. Server-side rendering
  2. Client-side rendering
Server-Side rendering

The HTML contents is generated at the server side and the browser then paints the generated HTML. The meta tags that are generated during the server-side rendering is available at initial load. So when your page loads, the meta tags present at the initial load is easily processed by the web crawling for content ranking.

Client-Side Rendering

The HTML contents are rendered dynamically through javascript and it is injected into the DOM tree. This takes a bit of a time to process and thus is not crawler friendly because crawler would then need to dynamically render content too.

From the above two types, you may understand why the Client-Side Rendering does not go well with the SEO optimisation

How is react component rendered in terms of SEO

React is a are Client-Side rendering framework, So the contents are loaded after the initial page load and when crawlers crawl the page they cannot find the routes or the meta tags that are loaded dynamically.

How NextJS solves the biggest problem of React?

The NextJS is a React framework built to handle the most important aspects of web development as well as keep the Good things from ReactJS.

Few features of NextJS is static routing (even for dynamic content), server-side rendering of pages.

The server-side rendering helps SEO optimisation and also you can build components using React.

What are methods you can render these pages for better SEO optimisation?

There are two methods where you can get data before the page renders

  1. getStaticProps and getStaticPaths

  2. getServerSideProps

getStaticProps and getStaticPath

The above code will get you the data before the page renders through this we can set the meta tags and og tags needed for SEO optimisation.

Let's 2 API endpoints.

1
2
3
4
5
6
7
8
9
10
//Filename: /main/pages/api/user/[id]/index.js

const sampleData = {
  0: { name: 'Hoo', desc: 'He is doctor' },
  1: { name: 'John', desc: 'He is engineer' },
  2: { name: 'Doe', desc: 'He is doctor' },
}
export default async function handler(req, res) {
  res.status(200).json(sampleData[req.query.id])
}

The above gets user data based on dynamic user id

1
2
3
4
5
//Filename: main/pages/api/user/index.js

export default async function handler(req, res) {
  res.status(200).json({ name: 'John Doe', desc: 'He is a doctor' })
}

The above gets static user content.

As you can see in the file name above we are using [id] square brackets which is then accessible as req.query.id. With that id, we can fetch users from a database or in our case we are going to use the above sample data.

Now that everything is set up for the data side, let’s move on to rendering pages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Filename: main/pages/user/[id]/index.js
import Head from 'next/head'
import Axios from 'axios';

export default function Home({ data }) {
  return (
    <>
      <Head>
        <title>{data.name}</title>
        <meta name='description' content={data.desc} />
      </Head>
      <div>Data</div>
    </>
  )
}
export async function getStaticPaths() {
  return {
    paths: [],
    fallback: 'blocking',
  };
}

export async function getStaticProps({ params }) {
  const { data } = await Axios.get(`http://localhost:3000/api/user/${params.id}`);
  if (data.status >= 300) {
    return {
      notFound: true
    }
  }
  return {
    props: {
      data
    },
    revalidate: 1,
  }
} 

The above code is an example of dynamic routing based on dynamic content. The route user/[id]/ would generate dynamic content. params.id in the function getStaticProps would fetch the data at the server side before rendering the React Components.

getStaticPaths should be coupled with getStaticProps so that this method works, as you can see fallback: 'blocking' which prevents page load before the server-side operation is completed.

The getStaticProps will handle the data fetching operations and would also cache the page so that subsequent page request is served via cache.

The below code will redirect to the 404 pages if no data is found for that user:

1
2
3
4
5
if (data.status >= 300) {
  return {  
    notFound: true  
  }
}

revalidate: 1 This will fetch the data after 1 second in case the data is changed in the backend since the frontend data is cached.

getServerSideProps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import Axios from 'axios';

export default function Home({ data }) {
  return (
    <>
    <Head>
      <title>{data.name}</title>
      <meta name='description' content={data.desc} />
    </Head>
    <div>Data</div>
    </>
  )
}

export async function getServerSideProps({ req, res }) {
  const { data } = await Axios.get('http://localhost:3000/api/user');
  return {
    props: {
      data
    },
  }
}

getServerSideProps fetches the data on page request, this would pre-render the page on every request and is likely slower than getStaticProps. The generated page content is not cached and thus must be used when the content of the page is to be generated afresh on each request.

1
2
3
4
5
6
7
8
export async function getServerSideProps({ req, res }) {  
  const { data } = await Axios.get('http://localhost:3000/api/user');  
  return {  
    props: {  
      data  
    },  
  }  
}

The above function will fetch the data and send it to the component as props. revalidate parameter is not being used with serverSideProps as the page would generated a fresh on each request.

You can find the project here