2020 Website & Gatsby Impressions

I recently redesigned and rebuilt my website from the ground-up. The last refresh was in 2015 and it felt like the website was becoming a little stale. It was previously built on WordPress and with not giving it as much attention as I should, the content got out of date and the performance began to dip.

Goals for this 2020 website were to keep it simple, make it easy to update, concentrate on putting portfolio content first, and at the same time give myself an opportunity to learn some new tech. I've had my eye on Gatsby for for a couple of client websites but never quite got the chance to use it, so now was the time. What follows are some of the challenges I faced and my impressions on Gatsby.

A screenshot of Ian's 2015 portfolio showing hero and portfolio items
My 2015 portfolio website

Preparing to Build

My previous website was based on WordPress and I also had a store powered by WooCommerce that I wanted to keep. In my initial research, it looked like it was going to be possible to continue to manage my content and store via WordPress and WooCommerce as Gatsby had plugins and many tutorials for integrating but it quickly became obvious that neither WordPress-in-Gatsby or WooCommerce-in-Gatsby plugins were fully realized. Whilst you can source content from both platforms, the features offered aren't paralleled in Gatsby. I could get the store content via the gatsby-source-woocommerce plugin but managing cart, checking out, etc would all be functionality I'd have to write myself. This is understandable, trying to recreate features in Gatsby and then maintain them would be time consuming.

The most efficient option was to leave the store as it was in WooCommerce. The store was never really contextually relevant to my portfolio or blog anyway and this gave me an opportunity to update to the latest version of WooCommerce and change to an official WooCommerce store theme rather than a custom built one that took more time to maintain. I moved the store from ianlunn.co.uk/store to store.ianlunn.co.uk and used DNS to point store.ianlunn.co.uk to the server it was originally hosted on. The Gatsby website would be hosted on Netlify at ianlunn.co.uk.

My initial intention for the WordPress content was to leave it in WordPress and source it via gatsby-source-wordpress at build time. Each time I ran the gatsby develop command to start a local development server, the source plugin would pull content from WordPress. I found this to be very slow. I imagine there are options that would allow for only targeting certain parts of WordPress to reduce the amount of time this takes and there's also a cache that means you don't have to do this each time, but I found I often had to clear the cache to work around other issues. As my WordPress content was already written in Markdown anyway, and I didn't really need the other features of WordPress, I decided to move away from it entirely and source my content directly in Markdown.

I used wordpress-export-to-markdown to convert WordPress content to markdown which worked extremely well. My WordPress content was already written in Markdown but this script saved a lot of time because it saved images and similar media in a suitable format and converted post properties such as slug and date to frontmatter (a simple format for assigning meta data in a Markdown file).

With the store its own entity on a subdomain and my content simply stored in the website repo as Markdown, it feels like a far better separation of concerns that is easier to maintain.

Gatsby

Being somewhat an old-school front-end developer that misses the simpler days of static pages uploaded to FTP and use of JavaScript as an enhancement rather than foundation, Gatsby felt like a good middle-ground between old and new. It offers some of my favourite modern developer experience features of React such as components (and Storybook) but to the end user has the benefits of a static site such as great performance. It has a lot of plugins already and in my experience, most were plug and play and supported the options I wanted.

One of the biggest selling points of Gatsby for me was how it had a lot of the trickier and more painstaking aspects of front-end development built-in and handled under the good so you can just get on with creating.

Gatsby Images

Gatsby aims to make working with images much easier for a developer. You give it one source image and it will deal with generating multiple sizes and formats, optimization, lazy loading, and so on. Although this to me is much needed, especially when images are often the biggest performance bottleneck for many websites, I did find working with images to be the trickiest aspect of getting to know Gatsby.

Firstly, you have to query images in Gatsby via GraphQL. It's not particularly hard to learn but it feels a little disjointed. You query the image in GraphQL, pass the query data into your page, then set your image source via the query data. It seems overly complex and a little messy.

The gatsby-image plugin is capable of displaying fixed and fluid (responsive) images and comes built with some of the advantages I mentioned above such as lazy loading. As the names suggest, a fixed image is one that maintains its size whereas fluid is a responsive image that will take take up the width of its container. If you want an image to be fluid up to a certain width, you need to add a maximum width to the container, something that wasn't immediately obvious to me.

I found a couple of bugs with gatsby-image:

  1. The automatically generated aspect ratio for images never seemed to be quite right, there was often a small amount of bleed outside of the image container. This was solved by manually defining the aspect ratio but I didn't understand why gatsby-image couldn't quite do this itself given that it knew the image width and height.
<Img
  fluid={{
    ...data.gettingStarted.childImageSharp.fluid,
    aspectRatio: 2480 / 1753,
  }}
  alt="Screenshot from Getting Started Hiring Ian Lunn PDF"
/>
  1. Art-directed images (multiple images for different screen sizes) will only use the first image's aspect ratio when server-side rendered.
const sources = [
  {
    ...previewSmall.childImageSharp.fluid,
    media: `(max-width: 1199px)`,
    aspectRatio: 850 / 1294,
  },
  {
    ...previewMedium.childImageSharp.fluid,
    media: `(min-width: 1200px) and (max-width: 1599px)`,
    aspectRatio: 1880 / 1316,
  },
  {
    ...previewLarge.childImageSharp.fluid,
    media: `(min-width: 1600px)`,
    aspectRatio: 2620 / 1294,
  },
]

In the above snippet I'm defining art-directed images and breakpoints that determine when each image should appear. This worked fine when developing locally but when viewing on the server, I noticed that all images would use the aspect ratio of the first image in the sources array. It turned out that during server-side rendering where the server doesn't know the size of the user's window, gatsby-image will simply output the first sources item. This is a known issue. My solution to this was to output each out the media queries inline on the page so the browser can choose the correct aspect-ratio:

let aspectRatioFix = ``
sources.forEach(({ media, aspectRatio }) => {
  aspectRatioFix += `
    @media only screen and ${media} {
      [class^="screenshots-module"] .gatsby-image-wrapper > div:first-child {
          padding-bottom: ${100 / aspectRatio}% !important;
      }
    }
  `
})

One final irritation with regard to images in Gatsby is that I wasn't able to transform images consistently. The gatsby-remark-images plugin is used to process images in markdown files and comes with options such as converting the image title to a caption. Another handy time saving feature but because gatsby-remark-images doesn't support gif and SVG formats, the transforms I am applying to gatsby-remark-images doesn't apply to gif and SVG. To work around this, when wanting to add a caption to a gif or SVG in markdown, I resort to using HTML to create the caption. A minor irritation but perhaps one that shows you often end up having to work around certain things in Gatsby or spend the time creating a plugin to do what you want.

gatsby-image was perhaps the thing that drew me to want to try Gatsby the most. I was a little disappointed having ran into the above hurdles but now I have a better understanding, I can work with it quicker in future projects. As the documentation states, gatsby-images isn't intended as a replacement for images entirely -- you might not find it suitable for all situations. I'm tempted to create my own images plugin for Gatsby that might not have all the same bells and whistles but aims to be easier by relying on relatively new web tech related to images such as native lazy loading.

Build Speed

If you plan on using Gatsby you should be aware of the build speed. My site, which is relatively small (although it has about 1000 images given that each image needs several different sizes and formats) takes around 6 minutes to build. If you plan on updating your website often, or sourcing your content from WordPress and automatically starting a Gatsby build each time WordPress is updated, you will want to take this into consideration. Given the build time, the idea of starting a build each time WordPress is updates is a no-go for me. This is especially true if you're building a website for a client that will be updating WordPress content -- I couldn't justify having them wait X amount of minutes before their changes appear on the live site.

It looks like there are ways to reduce build time, although they may be specific to the static-site service you use such as this Netlify plugin that maintains the gatsby cache during builds. Despite the possibility of optimizations, build speed will be a major factor when considering if Gatsby is the right tool for the next job.

It's also worth keeping in mind that many static-site services base their pricing on build minutes. From a sustainability point of view I actually like this because it gives developers an incentive to optimize build time and cut out unnecessary operations.

Netlify

I hosted the website on Netlify. This was incredibly easy to set up; the wizard has you link your Netlify website to a GitHub repo and it auto builds each time you update the repo. Each build is given a preview URL so you can test everything is working before publishing that build as live. The free starter package on Netlify is very generous. I needed to pay $7 for more build minutes in my first month but I can't imagine exceeding the free 300 build minutes now development is complete.

Conclusion

Gatsby has some great performance features and its heart is in the right place when trying to simplify certain areas of basic web publishing such as handling images. The learning curve was a little steeper than I had hoped but now having experienced the worst, Gatsby is another tool worth keeping in mind for future projects.

My aim when creating my portfolio was to do it in a short period of time. Gatsby enabled me to do that. There were some unexpected issues mentioned above that slowed me a little but these could probably be solved by digging deeper into Gatsby; creating my own plugin(s) and getting more involved with Gatsby's open-source community. Something for my next Gatsby project.

The two scenarios I see myself using Gatsby again are; for myself or tech-savvy clients when wanting to quickly build a fast website and for clients wanting a fast brochure website where I know they won't want to update the content themselves.

Useful? Buy me a coffeeUseful? Buy me a coffee

Ian Lunn is a Front-end Developer with 12 years commercial experience, author of CSS3 Foundations, and graduate of Internet Technology. He creates successful websites that are fast, easy to use, and built with best practices.