The Great Gatsby (Blog Transition)

Over the past several years, static sites have had a bit of a rebirth. Heralding back to the days of FTPing plain HTML and CSS files to a webserver, static site generators like Jekyll along with static hosts like GitHub Pages and Netlify have brought the power of plain HTML, CSS, and JavaScript to a newer generation of web developers. One particular area that static sites have excelled at is for generating blogs, like this one! In lieu of complicated setups like WordPress that required setting up a PHP environment along with a database, static-site blogs are meant to be simple to get up and running and simple to maintain. Being a forward-thinking group of folks, &yet has used a static-site for our blog for quite a while now. However, getting it up and running wasn’t exactly as easy as the “Getting Started with Static Sites” tutorials would have lead you to believe. At one point the initial setup was so complicated, and so unreliable for our developers, that we encapsulated the entire application inside a Dockerfile to make development easier. And I don’t know about you, but I don’t think a static-site generator should be so complicated as to require Docker to get up and running.

How’d you manage that?

Our previous site was built using a Python static-site generator. It was incredibly well-featured, and allowed us to do virtually everything we wanted to do. However, that power came at a cost. The code only ran on Python 2, so when macOS updated the system Python from 2 to 3, the Makefile that built the site suddenly stopped working for those working on the site (that was assuming you’d managed to properly install the dependencies the site required in the first place!). While these hurdles are easy to solve for lightly-seasoned Python developers, they were difficult roadblocks for our JavaScript-focused developers (which is the vast majority of our team). Adding Docker support was a bit of an improvement, but it was still asking a lot of our team, especially for something that was supposed to be simple and straightforward!

So how did you fix it?

Right around the time we were fighting with these issues, a little-known JavaScript static-site generator named Gatsby was experiencing a bit of a rise to fame. Gatsby promised to bring the quick initial loading of static sites together with the near-instant loading of a single-page-application while still feeling like a standard React application. The biggest question we had was this: will it be easier than what we have now?

With Gatsby, this is all that’s needed to get up and running:

$ git clone --recursive https://github.com/andyet/blog.andyet.com.git
$ cd blog.andyet.com
$ npm install
$ npm start

Thanks to Gatsby, the process for getting up and running with our blog is exactly the same as many of our other React and JavaScript-based projects. It no longer requires a specific version of Python at a specific path, no longer requires installing third-party modules into a global location, and most definitely doesn’t require Docker.

It sounds easier, but is it better?

One of the main reasons we chose Gatsby is that it’s both a static-site generator and a complete React application. This gives us the performance benefits of static-sites along with the client-side performance benefits of single-page applications. When you type in blog.andyet.com, the initial response contains all the HTML and CSS necessary for rendering our blog’s homepage. It renders just fine without any JavaScript, and will even work beautifully in a browser with JavaScript disabled. What happens next is the magical bit. Gatsby then “rehydrates” the React application, which handles subsequent navigations. When you click on a blog post title, instead of going to the server and requesting the HTML and CSS all over again, Gatsby requests just the content of the blog post, which is able to be delivered in just a handful of gzipped kilobytes. Gatsby also does some really nifty things like loading the content of the post the moment you mouse over a title, that way when you actually click on it, the blog post’s content has already been retrieved from the network.

Okay, that makes sense. But how hard was it?

Moving from our previous static-site generator to Gatsby was actually surprisingly easy. We store all of our blog posts in a separate repo (hence the --recursive flag above), so the only slightly tricky bit was telling Gatsby how to properly parse all of our existing Markdown files. We also had to port a few complex features like related posts and archives, but because our entire team is familiar with JavaScript and React, it was a fairly straightforward operation.

To start, we copied over all of our style assets, written in Stylus. Thanks to gatsby-plugin-stylus, we were able to easily reference our primary stylesheet inside of our default layout component. This ensured that our entire stylesheet was loaded at the root of the application. Our complete stylesheet is only 9KB gzipped, so it’s sent as an inline stylesheet with the initial document. This ensures that after the initial network request, there’s no other render-blocking network request.

Once we had our stylesheet being loaded, building the rest of the site was basically just copying and pasting the original templates, replacing template strings with their Gatsby-equivalents. Our existing templates were arranged in virtually the same exact way that Gatsby wanted, so the bulk of the modifications were simply replacing class="" with className="" for React.

As was mentioned earlier, the most complicated portion of the transition was reimplementing two features our previous static-site generator gave us for free: related posts and archives. For related posts, we pick the posts with the highest “tag affinity”, which is basically the posts with the highest number of shared tags with the current post. We then add these related posts to our page context in the call to createPage.

Our archive pages were also pretty easy to build with Gatsby. We use a year-specific GraphQL query to get a list of all posts for a given year, and then generate a new page listing each of those blog posts. We then provide each page with a list of the years for which we have blog posts, and render a year selector at the bottom of every page.

Was it worth it?

In the end, the simple fact that our blog’s build process now mirrors the vast majority of our other projects is worth it in and of itself. Along with that, we get a UI system that’s familair to our entire team, the best loading experience from both static sites and client-side rendered applications, and the ability to grow and add other more complex features in the future like service workers.

So yeah, we think it was worth it!

You might also enjoy reading:

Blog Archives: