The beauty of Gatsby
Gatsby is a beautiful tool for building static sites with modern tools.
It leverages the component architecture of React, and cleverly server-side renders
your site at build-time to generate a static website, ready to go.
All you have to do is export a component from any *.js
file in the auto-generated src/pages
directory in your project, and it'll create a route when it builds your static website based on the name of that file. That alone is enough
to get a static website off the ground in no time!
Gatsby also supplies a slew of build hooks you can write functions for in order to generate pages, GraphQL nodes, wrap your app with a component, and just about everything in between.
The problem with Gatsby
When creating a website, it's nice to have a single source of truth when creating
routes. Endpoints are the backbone of the internet, and managing them in a
quickly growing application can become tiresome if there isn't a single module that you can point to for truth.
With regards to routing, Gatsby's biggest strength is also its biggest weakness;
the src/pages
directory, as magical as it sounds, supplies no means of referencing the paths that are built based on the filenames. That means in order to link to another page in your site, you have to hard code the reference as a string to another page. Gross!
My solution
If you want to just peak at the final solution, here's a link to the repo.
We're going to use Gatsby's createPages
build hook in order to create our routes. Gatsby uses Redux under the hood in order to maintain state, and passes bound action creators to all of its build hooks. We'll use the createPage
action creator within the creatPages
build hook. I'll walk you through every step, starting with generating a fresh static site with Gatsby's build tool.
If you haven't installed it, run the following in your command line:
npm install -g gatsby
Generate the website
This is the easy part! To create a new Gatsby site in the gatsby-routing
directory, run the following command:
gatsby new gatsby-routing
Setting up the routes
Let's create a directory src/routes
, and move index.js
and page-2.js
from src/pages
to the new routes directory. Rename index.js
to home.js
.
After that, create a new file called index.js
, and put the following code
inside it:
// src/routes/index.js
const path = require('path')
const routes = {
home: {
path: '/',
component: path.resolve(__dirname, 'home.js')
},
page2: {
path: '/page-2',
component: path.resolve(__dirname, 'page-2.js')
}
}
export { routes }
We have to use Node APIs like path
instead of ES6 import
because we'll be
requiring this file in Gatsby's gatsby-node.js
file. Let's set these routes up
so they're ready to render - open gatsby-node.js
and place the following
code inside.
const { routes } = require('./src/routes')
exports.createPages = ({ actions }) => {
const { createPage } = actions
Object.keys(routes).forEach(route => createPage(routes[route]))
}
So in createPages
we use the createPage
action creator to make new pages,
using the objects from the routes
object that we imported. createPage
takes
an object with a path string and a React component to render for that path,
and an optional context that you can pass to the React component as props.
Run gatsby develop
from the root of your project to see the effects!
Converting links to reference our routes
If you look inside the components in the src/routes
directory, you'll notice
we're still hard-coding paths in our links. Let's fix that now!
First, let's unnest our routes and create an object with the same keys as our
routes, but with just the path strings as their values. Your src/routes/index.js
should now look like this:
// src/routes/index.js
const path = require('path')
const routes = {
home: {
path: '/',
component: path.resolve(__dirname, 'home.js')
},
page2: {
path: '/page-2',
component: path.resolve(__dirname, 'page-2.js')
}
}
// Same keys as 'routes', but the value is only the path.
const paths = Object.keys(routes).reduce((acc, route) => {
acc[route] = routes[route].path
return acc
}, {})
export { routes, paths }
Now let's import our new paths
object, and use it to link around our Gatsby
site!
// src/routes/home.js
import React from 'react'
import { Link } from 'gatsby'
import Layout from '../components/layout'
import { paths } from './'
const IndexPage = () => (
<Layout>
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<Link to={paths.page2}>Go to page 2</Link>
</Layout>
)
export default IndexPage
// src/routes/page-2.js
import React from 'react'
import { Link } from 'gatsby'
import Layout from '../components/layout'
import { paths } from './'
const SecondPage = () => (
<Layout>
<h1>Hi from the second page</h1>
<p>Welcome to page 2</p>
<Link to={paths.home}>Go back to the homepage</Link>
</Layout>
)
export default SecondPage
And just like that, we're no longer hard-coding our site's paths in any of
our components! Now creating a new route is as easy as creating a new component,
and adding it to src/routes/index.js
.
Wrap-up
If you're new to JavaScript, or want to learn React, Gatsby is a great place to
start. I'm in the process of building a large application, and can't afford to
be hard-coding URLs into my app. I hope that this helps someone else that's in
a similar situation!
This is my first official blog post, I'd love some feedback :)
Top comments (1)
Nice :) Note that
export { routes, paths }
should be
module.exports = { routes, paths }