My Javascript Journal

Thursday, May 21, 2020

Converting a React Site to Gatsby (part 1)

Background

We've spent a lot of the last two years travelling around Europe in our motorhome and before we went I set up a website to keep a record of our progress. I wanted to build the front-end in React; the back-end was Wordpress because I know it and it's easy for my wife and I to add content. This was all using the REST API to pull the data from Wordpress.

On the Wordpress end we designed a hierarchical page structure for the places we went to:

root
--Town 1
--Town 2
--Town 3
--Town 4
--Town 5
--Town 6
--Town 7
--Town 8
--Town 9
--Town 10

Metadata about GPS location, arrival and departure dates were recorded in the custom fields for the page. Photos were added as galleries to the page. We also wanted a blog post section on the website for occasional random posts.

Issues

The website seemed to work quite well at first. However after a few weeks slowdowns began to creep in. The Wordpress API was taking a long time to return the data. We compensated as best we could by splitting the places we visited by first country and then by year (see below). This reduced the size of the returned data for each call but resulted in more round trips to the server to parse the tree. But still if you wanted the map for the whole trip it would take a very long time to retrieve the whole thing.

root
--Year 1
----Country 1
------Town 1
------Town 2
----Country 2
------Town 1
------Town 2
------Town 3
--Year 2
----Country 1
------Town 1
------Town 2
----Country 2
------Town 1
------Town 2
------Town 3

Resolution

I'd been reading about static generators like Gatsby and decided to give it a go and see what could be done. The good thing about Gatsby is that it's still React although its behaviour is a bit different. The components that we had before could still be used with most of the HTML and CSS untouched. There was a fair amount of work to do though to create the templates. We had to create a map page and a gallery page for each town as well as a photo page for each photo.

So we start with the following directory structure for our project

src
--pages
----index.js
----blogSummary.js
--templates
----BlogPostTemplate.js
----MapTemplate.js
----GalleryTemplate.js
----PhotoTemplate.js
--components
-----  ... all original components

The following snippet from gatsby-config.js shows the plugins that we use:

  plugins: [
{
resolve: "gatsby-source-wordpress",
options: {
baseUrl: wpURL,
protocol,
hostingWPCOM: false,
useACF: false,
excludedRoutes: [
"**/users/**",
"**/comments",
"**/settings",
"**/themes",
],
keepMediaSizes: false,
},
},
{
resolve: 'gatsby-transformer-sharp',
},
{
resolve: 'gatsby-plugin-sharp',
},
{
resolve: 'gatsby-plugin-react-helmet',
},
{
resolve: 'gatsby-plugin-react-leaflet',
options: {
linkStyles: true,
},
},

The gatsby-source-wordpress plugin reads the Wordpress API completely and builds a GraphQL server for the duration of the build process. gatsby-node.js contains the code that drives the build process. It needs to create all the pages of the site. This is something that used to be done dynamically for each page visited. Instead we had to iterate through all the years, then each country and then each town, building a map page for each town and a gallery page for each town. Further for each town we had to produce a different page for each photo. This is a snippet showing the production of a map page:

createPage({
path: `${countryMapLink}/${town.slug}`,
component: MapTemplateSingle,
context: {
ids: [town.id],
towns: [town],
gps: town.gps,
zoom: 13,
},
})

This passes control to the MapTemplateSingle.js template with data passed via context.

Of course there were a number of gotchas in this. I'll go through some in Part 2.

Articles