How we improved our core web vitals by migrating to Gatsby
By migrating the architecture of this website to Gatsby, we were able to double key core web vitals, increase our accessibility rating by 50%, and boost our SEO scores from 80 to 100
The web is constantly evolving. New tools and platforms for making websites faster, smoother, and more accessible are emerging all the time. As a developer, content owner, or anyone else with a stake in the performance of a company’s website, it’s not only important to be aware of all of these developments, but also to be selective about which ones to adopt. Obsessing about performance metrics can easily lead down an infinite rabbit hole of infrastructure projects, and divert engineering attention away from core development work with more direct potential to enhance user experiences. At the same time, however, neglecting problems that stem from an outdated site architecture can make your eventual migration projects bigger time investments than they have to be.
In late 2020, we at mParticle decided it was time to change the engine that powers our website. At the time, the site you’re currently visiting was based on a template aimed at building server-side rendering React components that could be updated on the fly with a CMS. While this build did have some features we were happy with (namely the use of React components, SASS/CSS modules, and code splitting), the site performance and developer experience just wasn’t up to our standards.
First and foremost, we wanted to deliver faster and smoother on-page experiences for our users, and to improve the site’s accessibility features significantly. Additionally, we were interested in enhancing the developer experience––we wanted building, maintaining, and contributing to the site to be smoother for all stakeholders involved, from our developers who work on the site every day, to contributors who update and add new content through our CMS.
Finally, Google has made it clear in its most recent page ranking algorithm update that SEO performance will depend heavily on load times and other metrics that reflect a user's on-page experience. Of course, we wanted to be prepared for this, and Gatsby delivers the performance gains we needed to be poised and ready.
Weighing the options
In comparing different solutions, Gatsby and Next.js quickly emerged as the two frontrunners in our search for a new engine to power our website. Both of these frameworks excel at delivering considerable performance gains and SEO benefits. They both also leverage React to build UI components and content templates, and benefit from the active and enthusiastic community of developers around this framework.
Here is a breakdown of some of the differences between Gatsby and Next.js we weighed when deciding between these two solutions:
Deciding on a new engine
Both Gatsby and Next.js are excellent choices for building extremely performant sites, and they each offer great developer features as well. In the end, we decided to go with Gatsby, for a few key reasons. We were already using Prismic as our CMS, and we wanted to continue doing so. We found that using GraphQL (Gatsby’s default querying method) to query content from Prismic to be extremely efficient and developer friendly. One of the great strengths of GraphQL is that it allows clients to fetch related data in a single request, rather than making calls to multiple endpoints as one would have to with a REST API. Using GraphQL would theoretically still be an option were we to use Next.js, though we would need to employ Apollo as a wrapper for our queries.
The specificity of GraphQL queries comes in particularly handy on pages like the one you’re currently viewing, for example. To build out all of the content that is displayed on an article page, we need to retrieve data from multiple Prismic documents. Instead of sending several requests to different API endpoints, however, we are able to write one very versatile query within the Article template that retrieves all the data we need.
Most of this query is retrieving data about the article itself, but as you notice, this page also has a component for the author, and a section below the text displaying related content. To fetch the appropriate data for building the Author modulet, we added the following to the template query:
author {
document {
... on PrismicPerson {
data {
name
title
photo {
alt
url
localFile {
childImageSharp {
gatsbyImageData
}
}
}
}
}
}
}
Below the content you’re currently reading, you’ll see a list of articles under the heading “Latest from mParticle.” To populate the attributes of these articles, we did not have to query an additional API endpoint containing data specific to articles––instead, we were able to explicitly state the data this section needed to include within the main query for the Article module:
related_articles {
article {
document {
... on PrismicArticle {
id
uid
type
data {
invisible
featured
author {
document {
... on PrismicPerson {
data {
name
}
}
}
}
intro_text
category {
document {
... on PrismicArticleCategory {
data {
name
}
}
}
}
publish_date
event_date
image {
alt
url
localFile {
childImageSharp {
gatsbyImageData
}
}
}
thumbnail {
alt
url
localFile {
childImageSharp {
gatsbyImageData
}
}
}
title
article_type
}
}
}
}
}
In addition to our preference for GraphQL, another factor driving our choice to use Gatsby was the fact that we had already built our documentation site with this framework. This means we already had institutional knowledge of Gatsby, and our engineers were already impressed by the performance gains it had delivered on the docs site. Finally, since Gatsby’s developer base is rapidly expanding, we are confident that we will be able to quickly find and onboard new Gatsby-proficient developers to work on the site should that need arise in the future.
Flocking to a new Github repository
As a first step, we created a new Gatsby-specific repository that would eventually serve as the new website’s home. After making the initial commits to this new repo, we connected it to Gatsby Cloud to be able to preview the site under development. Gatsby Cloud comes with very useful CI/CD features out of the box that significantly improves the processes of update deployments and site rebuilds. The incremental builds feature, for example, means that only the files that have been changed are updated when a rebuild is triggered, which occurs whenever a new PR is merged into the main branch of the repository.
Since the website’s previous build was based on React, we were able to directly port over many of the original components into the Gatsby site architecture in the new codebase, which looks like this:
Here are some features of the codebase:
- The /schemas directory contains JSON files that contain all of the data that will be presented in the website. These files are returned from Prismic as the result of GraphQL queries made inside the individual components that will render the data.
- /createPages contains React components that build pages that build dynamically from the components and templates found under the /src directory.
- /src includes the components that are used in pages throughout the site. Each component is built with a modular pattern in a package that includes the Component.js file, an index.js file (serves as an external reference for the component), and a Component.module.scss file that contains the component’s styles.
- Gatsby-config.js is the main configuration file for the site that specifies all of its metadata and initializes plugins.
While migrating the UI features was relatively straightforward, the larger lift from a development perspective came from the data layer. In the previous build, we were using a traditional REST API to retrieve data from Prismic, but since Gatsby is based on GraphQL, all of the data queries had to be entirely rebuilt using this technology and the gatsby-source-prismic plugin. The work to migrate these API calls to GraphQL was labor intensive, but we are confident that in the long run, the efficiency gains from using GraphQL as a data retrieval mechanism will make it well worth the effort.
Early payoffs in performance and developer experience
From start to finish, the entire process of migrating our website took approximately three months. We officially pointed the site’s DNS to the Gatsby repository on April 2nd, 2021, and we’re already seeing results in the form of improved metrics in the key areas we set out to address. Our scores on Lighthouse, Google’s benchmarking tool, have already improved dramatically:
On the development side, we are already reaping the benefits of Gatsby’s efficient workflows and best-in-class resources for building new features and maintaining old ones. For one, we are loving the extensive ecosystem of plugins maintained by the Gatsby community that make things like querying Prismic, maintaining a Progresive Web App manifest, and optimizing images much easier. Plugins from which we’re seeing particular value include gatsby-source-prismic, gatsby-plugin-csp, gatsby-plugin-image, and gatsby-plugin-manifest.
As we knew would be the case, using GraphQL to make efficient queries that avoid over- and under-fetching is a significant advantage that makes query writing and data planning much more efficient. Additionally, GraphQL playground––a tool maintained by Apollo that allows you to visually explore an API source––has been a fantastic resource to use for on the data side of the stack as well. If we have any minor complaints at this point in our journey with Gatsby, it’s that GatsbyCloud’s incremental build times are longer than we would like them to be. This is to be expected with a static-site-generator working on a site with as many pages as ours, so in some ways, this was an anticipated trade-off.
All in all, however, we like our new home, and we’re looking forward to continuing to leverage all that Gatsby has to offer to make our site an even better experience for our users.