Single Page Apps with Gatsby
Gatsby, which is a static site generator, is famous for blogs and documentation websites. But there is no wrong in build full blown React apps with it.
In the case of a blog, Gatsby builds a page for every article at the build time and generates a directory which can be hosted directly. But when it comes to Single Page App (SPA), we have only one index.html
at the root, and the components are loaded depending on the route that the user is in.
We can get the benefits of code spitting with some React lazy suspense features with some minimal extra work too.
jsx1const Contact = React.lazy(() => import('../components/Contact'));2const LazyContact = (props) => (3 <React.Suspense fallback={'<p>Loading...</p>'}>4 <Contact {...props} />5 </React.Suspense>6);7
The Contact
component is loaded only when it will be rendered, which is when we hit a particular route. We will have a look at the routes in a moment.
But wait
Before that, we need a gatsby-node.js
file to let Gatsby know that we want all the route to end up in index.html
After cloning Gatsby's Default starter, let's add this file.
js1// gatsby-node.js23exports.onCreatePage = ({ page, actions }) => {4 const { createPage } = actions;5 if (page.path === `/`) {6 page.matchPath = `/*`;7 createPage(page);8 }9};10
Now we are ready.
Components for each Routes
Let's plan to have two routes, /contact
and /about
. In src/components
we will create basic components like this.
jsx1// src/components/Contact.js2import React from 'react';34console.log('contact component');56export default function () {7 return <div>Contact Us as you like.</div>;8}910// src/components/About.js11import React from 'react';1213console.log('about component');1415export default function () {16 return <div>We are a great bunch of people</div>;17}18
I've added the console logs to check when this file is loaded. We don't want it to load at the homepage. Rather only when the route is visited.
Main App
In the main page, which is src/pages/index.js
we make use for @reach/router
which Gatsby itself, uses for routing.
jsx1// src/pages/index.js23import React from 'react';4import { Router, Link } from '@reach/router';56const Contact = React.lazy(() => import('../components/Contact'));7const About = React.lazy(() => import('../components/About'));89const LazyComponent = ({ Component, ...props }) => (10 <React.Suspense fallback={'<p>Loading...</p>'}>11 <Component {...props} />12 </React.Suspense>13);1415const Home = () => <h2>Hello and Welcome</h2>;1617const IndexPage = () => (18 <div>19 <h1>Hi people</h1>20 <Link to="/">Home</Link>21 <br />22 <Link to="/contact/">Contact</Link>23 <br />24 <Link to="/about-us">About Us</Link>25 <br />2627 <input />2829 <Router>30 <Home path="/" />31 <LazyComponent Component={Contact} path="contact" />32 <LazyComponent Component={About} path="about-us" />33 </Router>34 </div>35);36
LazyComponent
renders the Component
we pass to it as a prop under React.Suspense
with a fallback.
If you build this project and serve, you can open the Networks tab in the browser console and see that a new JS file is loaded when you hit the /contact
route for the first time.
That's it, this is all we need to make an SPA using Gatsby.
Here is a working codesandbox link - https://codesandbox.io/s/gatsby-starter-default-yf72w
By Aravind Balla, a Javascript Developer building things to solve problems faced by him & his friends. You should hit him up on Twitter!