3

Moving to a static site with Gatsby + Netlify + Contentful

 10 months ago
source link: https://flexport.engineering/moving-to-a-static-site-with-gatsby-netlify-contentful-51125d443231
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Moving to a static site with Gatsby + Netlify + Contentful

Flexport has been growing at an extremely rapid pace in the last few years. As the organization scales, we are continually replacing solutions that were “good enough” at the time with more scalable, optimal solutions.

One recent example is our public-facing web pages. Until recently, our public pages were served by the same React+Rails app that serves our main application. We made copy changes manually, and just edited strings in code and deployed as necessary.

But at a certain point, using developer resources to make changes to our marketing materials slowed down both the Engineering and Marketing teams. And while the site wasn’t exactly slow, it wasn’t nearly as fast as we knew it could be.

So when the Growth team was tasked with undertaking a full-site redesign (as part of our recent rebrand), we started thinking about ways that we could update our public site architecture to better serve the needs of the organization.

Our main goals were:

  • To allow Marketing to make copy updates (in multiple languages) without requiring code changes
  • To dramatically improve site performance (including in global markets and on mobile devices)
  • To use the tools that our engineers are already using in our frontend stack (like React, Flow, GraphQL, etc)

These requirements pointed us towards using an architecture with the following structure:

  • a React-based static-site generator (familiar tools)
  • …deployed to a CDN (for extremely fast site performance)
  • …with content powered by a headless Content Management System (to allow non-engineers to push copy changes)

Our new stack

1*EXij-CSax-7XJyc-HQh_wQ.png

The new flexport.com

After experimenting with a few different configurations, we ultimately landed on a setup using the following tools:

Gatsby.js

Gatsby.js is a React and GraphQL-based static-site generator. Gatsby creates a React app that you run on a local dev server, with a build step to generate static versions of your pages.

Since it uses React, Gatsby allows you to utilize the whole React/JavaScript ecosystem. For us, that includes Flow, Aphrodite, ESLint, Prettier, and many others.

Gatsby provides plugins for connecting to external data sources (like a content management system). It then allows certain components to define GraphQL queries against those data sources, passing the result of the query in as a “data” prop to the component.

When you’re ready to deploy, Gatsby’s build process takes your React app and creates static versions of the pages in your app, ready to be pushed to a hosting service.

Netlify

Netlify is a service for hosting static pages on a global CDN.

Netlify is intended to be used with static-site generators like Gatsby, Hugo or Jekyll. Netlify listens for changes on a Github repo. When that repo changes, Netlify will pull the latest version of the app and then run a predefined build step, powered by the static-site generator.

Netlify then takes the static pages from that build process and pushes them to a global CDN.

Netlify also provides tools for managing deploys, making it simple to rollback or re-try deploys as necessary.

Contentful

Contentful is a headless Content Management System (CMS).

Unlike a traditional CMS (like Drupal or Wordpress) which combines the content management with the presentation of that content, Contentful focuses only on providing tools to enter and update content.

Contentful then exposes API endpoints that allow you to retrieve that content, either as JSON or using GraphQL.

How it all fits together

0*9zxNAmJOFeF4pMrp

The process works like this:

  1. When a new change is merged into the master branch of our Github repo, Github triggers a webhook that Netlify is listening for.
  2. Netlify, on receiving notification of a new change, pulls the latest version of the app from Github, and run the “build” command for the site.
  3. The Gatsby “build” command runs, grabbing the most recent content from Contentful. When the data is returned, Gatsby uses the returned information to generate static versions of our public pages, storing them in a “/public” directory
  4. On completion of the build step, Netlify pushes the contents of the “/public” directory to its global CDN

Reflections, two months in

We launched the new site in March — here’s what’s gone well (and not-so-well).

The Good

Speed

Gatsby claims to build “blazing fast” websites, and in our experience that’s true. The combination of Gatsby and Netlify has been a huge boost to our site’s performance (check it out for yourself: www.flexport.com). 🚀 😍

Gatsby’s use of GraphQL

Though using GraphQL was not a hard requirement for our project, it’s turned out to be an excellent fit.

As mentioned earlier, Gatsby allows certain top-level components to define GraphQL queries, which then get passed in to the component as a prop. Since we’re using GraphQL for data and Aphrodite for our styling, often the styles and queries for a component live in the same file as the component itself.

Here’s an example:

Being able to update component logic, styles and data in the same file is really pleasant, and makes updating our code simple and fast.

GraphQL also works well with our use of Flow for type-checking. We use Apollo to generate Flow types based on our GraphQL schema, so we have a high level of confidence that the props our components expect actually match the data they’ll receive.

Finally, Gatsby ships with built-in GraphiQL integration, which provides a great way to interactively query your data during development.

Netlify extras

Netlify has also been an excellent fit for our project. Apart from being fast, it comes with some great features that have made our workflow easier.

One unexpected highlight of using Netlify is their auto-generated Preview Deploys.

0*qVyZ1CS-_T-vGNZE

Whenever you create a new PR, Netlify will automatically create a preview build of the site and supply a link in the PR. These previews are extremely useful for sharing changes with designers and PMs, or for confirming behavior that might differ between the local dev environment and the deploy environment.

And if you set your build script to run your test suite, i.e.:

…then you can use this preview generation step as a simple CI process.

Netlify support has also been excellent. Netlify’s support team helped us debug several issues during development, and they were always quick to respond over email and chat. Very helpful.

The Bad

Contentful GraphQL placeholders

Contentful allows you to create models of your data in their system, but the actual fields they return in your GraphQL requests might change based on the content your editors supply.

For example, say you have a Blog Post model, with 3 fields (title, subtitle and body). Title and body are required, but “subtitle” is optional. You have three instances of the Blog Post type (1 with a subtitle and 2 without):

When you’re building your GraphQL query, you request the three fields:

With Contentful’s GraphQL implementation, that will work fine with the three blog posts in their current state.

But say that one of your content editors removes the “subtitle” field on Blog Post 3. Now, all of your Blog Posts have a “subtitle” field with null as its value. Contentful will see that all of your instances of that type have “null” as their value, and it will strip that field from the response payload.

That means that your GraphQL query is now asking for a field that Contentful doesn’t return, so you’ll get an error:

This is pretty unfortunate, as it means that editors of your CMS have the ability to introduce errors in your build process.

The simple (but unfortunate) workaround is to keep one instance of each of your models around as a placeholder, with a value in all fields. But there’s no way to ensure that even this placeholder won’t get accidentally deleted.

Netlify redirects

Here’s something else to be aware of if you’re planning to put a Netlify-powered site in front of an existing app:

We have been directing traffic from www.flexport.com to our primary app for some time, so the “www” subdomain serves many different types of traffic (requests for public pages, but also things like webhooks integrations with various services, etc).

When we decided to use a Netlify-hosted site for our static pages, we knew we would have to redirect some requests through to our existing app for any traffic that wasn’t for a public-site page.

Netlify allows you to define certain URLs that it should redirect. The major limitation is that those URLs will not pass on query params by default. You can define which query params a given route should pass along, but you have to enumerate all possible combinations of query params. So if you have query params A, B and C, you have to create rules for when A is present, when A and B are present, when A and C are present, when B is present…

So if you’re trying to put a Netlify site in front of an existing site, you should be aware that any site that you are redirecting to will have limited ability to receive query params.

Summary

Overall, our experience with this stack has been very positive. We’ve ended up with a very fast site, with a great developer experience and the ability to update content without additional work from the Engineering team.

Aside from a few relatively-minor caveats, these tools have served us very well. We hope that they will continue to be reliable and fast for years to come, or at least until the next rebrand 🙂.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK