reactjsseosingle-page-applicationgoogle-searchgooglebot

How to achieve SEO for React SPA without SSR or prerendering. And preferably keep the code portable e.g. no vendor lock-in


The SEO topic has been debated to an extraordinary length and React SPAs are very common. Yet searching SO yields no clear coding guidance complimented by a simple to follow sequence of specific practical steps required to deploy a React SPA and achieve SEO.

The existing Q/A are either not very helpful or use links. This question is not related to React, the detailed answer considers deprecated AJAX technology. Although its upvote and viewing counts show the importance of this topic.

Searching beyond SO yielded the official Create React App (CRA) page. To create a minimal reproducible example I followed the steps:

  1. Executed commands:
yarn create react-app my-cra
cd my-cra
yarn add react-router-dom
  1. Replaced the content of the generated src/App.js file with the code:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Page1 from './Page1';
import Page2 from './Page2';

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Page1 />} />
        <Route path="test" element={<Page2 />} />
      </Routes>
    </BrowserRouter>
  );
}
  1. Added a file src\Page1.js:
import { Link } from "react-router-dom";

const Page1 = () => {
  return (
    <>
      <h1>Page1</h1>
      <Link to="/test">To Page2</Link>
    </>
  );
};

export default Page1;
  1. Added a file src\Page2.js:
import { Link } from "react-router-dom";

const Page2 = () => {
  return (
    <>
      <h1>Page2</h1>
      <Link to="/">Back to Page1</Link>
    </>
  );
};

export default Page2;

The React SPA works as intended and naturally uses client side routing. GitHub Pages deployment was chosen since it doesn't require to introduce vendor specific code. However the problem is that according to the Notes it will be necessary to use either routing with hashes or this repo. Hashes are not acceptable because Google explicitly disallows URLs with hashes for SEO. The repo is not an option either since the author suggests another solution if SEO is important.

So the question is how to get indexed by Googlebot without replacing BrowserRouter used at the step 2 with HashRouter in a simple React SPA. Another solution, apart from CRA + GitHub Pages can be suggested.


Solution

  • The answer is meant to demonstrate an easily reproducible set of steps to get a React SPA indexed by Google without any need of SSR or prerendering. It's split into two parts with headings:

    The first part is all about building a deploying a sample React application. Only one bullet point (that deals with title and canonical) is specific to SEO.

    The second part is all about SEO, however it's not specific to SPA or React.

    Website Deployment

    The deployment is based on Crisp React boilerplate (I'm the author) and uses Cloudflare Pages.

    This particular boilerplate has been chosen due to its features, like the variety of deployments, both Jamstack and full stack. It makes it easy to alter the deployment described below and switch from Jamstack to full stack if need be. The ready-to-replace Structured Data placeholders provided by the boilerplate could help with further SEO improvements once the website is indexed by Google.

    The steps:

    Requesting Google to Index the Website

    Add some original content to the webpages to avoid duplicate content.

    You can choose either passive approach and simply wait until Googlebot discovers your website or proactively ask Google to index it. If you choose the latter, use Google Search Console (GSC):

    The last 3 steps will have to be repeated for each SPA page.


    The deployed website lacks commonly used, though not strictly necessary for SEO files, such as sitemap.xml and robots.txt. Sitemap is more important for the passive approach. The robots.txt file is not needed unless you want to put some crawling restrictions in place.

    The website doesn't use all Crisp React features e.g. the ability to split a React app into multiple SPAs and selectively prerender the landing/index page of each SPA for better performance. If you need this functionality along with SEO, consider switching to full stack build or using a Cloudflare Worker as described in this article.