component which can often be used as a replacement for a standard <img />
. Whilst configurable, it's also fairly opinionated coming with its own interpretation how to display an image. At the time, it wasn't possible to use loading="lazy"
to enable native image lazy loading and instead had to use its own JavaScript-based solution.
As I didn't feel comfortable losing control over my image markup, I ended up writing my own markup and stitching together a number of other plugins to handle the resizing of images and replacing images within post content.
This proved brittle, with extra dependencies to maintain and problems with different versions breaking the functionality. Whilst I could've built the functionality myself and bypassed the need for the high-level plugins it ultimately felt like the approach being recommended by Gatsby pushes for plugins first, custom development second.
Once I'd got a working solution for my images, the next challenge became slow and fragile builds. I seemed to be spending more and more time frustratedly waiting for builds to happen. Partly, this was inevitable due to wanting to include a fair bit of image optimisation but still if a site with a dozen pages is slow to build that doesn't give me much faith for how well the system will scale out.
Most frustratingly of all, these builds were also fragile. Most of the attempts to improve build performance required using caching, which frequently resulted in builds that either didn't include my changes or would feature broken images.
A bit of research highlighted that I wasn't the only one facing build problems, including a now infamous Twitter thread by Nat Alison which shows that build times were just the tip of the iceberg when it came to problems.
Seeing as I was almost finished, I thought I'd keep going and then review my options. Taking a look at my completed site, it felt a bit more complex than I'd hoped for a first iteration and a developer experience that was already compromised.
It wasn't slow, especially with client-side navigation, but there was definitely a noticeable initial cost to downloading the JavaScript that this required. I started to question both Gatsby and using React. If the page itself was light enough, a new page request should feel as fast as a client-side page navigation.
Whilst my experience with Gatsby didn't find anything earth-shatteringly wrong, it did feel like the wrong tool for me. So, based on my experiences I decided to look for an alternative.
There were two paths I explored, the first being to keep going down the React path but using Next.js instead of Gatsby. The second option was to double-down on the static site generation aspect of my tooling and use a tool that focuses pruely on that, and not on then hyrating a client-side React application as well.
The Next.js option was tempting as it has proven to be a mature solution at work that was very flexible and not too opinionated, whilst the built-in image solution is far closer aligned to what I was looking for. Next.js would still hydrate in the browser and support client-side routing but it was also possible to disable this entirely to remove the client-side runtime to no longer use React in the browser.
In the end, I decided it would be more interesting to try something different and stick to the ethos of keeping things simple. I'd been hearing a lot of people having success with Eleventy, which is a static site generator similar to Hugo and Jekyll used for taking templates and transforming them into HTML.
Whilst Eleventy, Hugo, Jekyll, Next.js and Gatsby may all do static site generation they fall into two distinct groups. In the first group, Next.js describes itself as "The React Framework for Production" whilst Gatsby uses "One Front-end to Rule Them All". Both are JavaScript frameworks where static site generation is just one of many features.
Meanwhile, Eleventy describes itself as "a simpler static site generator". Eleventy, Huge and Jekyll all fall into the second group of tools which focus purely on static site generation without adding in any other extras or opinions.
This aligned nicely with what I was looking to do, so I ditched React and Gatsby, and started working on migrating over to Eleventy.
One of the first choices to make with Eleventy is which templating language to use. It supports a range out of the box, including JavaScript, Markdown, Nunjucks and Liquid and you can use a mix of them if you so desire. I started out using Nunjucks, but came across a few limitations with async logic within macros which led me to settle on using Liquid instead.
This migration meant moving my React components to Nunjucks, and handling the data flow from Ghost into Eleventy but otherwise I was able to keep most of the setup the same with only very minimal changes to markup and styling during this move.
After my experiences using Gatsby I paid particular attention to how Eleventy would handle images. Eleventy has a first-party plugin for handling images which is far lower-level than gatsby-image. Instead of giving up control over of my image markup, eleventy-image will handle resizing and transforming images and return JSON data which I can then use to construct image markup as I choose. If you'd rather, you can let it also build the HTML for you. If you do, it's far less opinionated with the only requirement being to provide an alt
attribute – which is the kind of opinion I can get onboard with!
For images within content, which is markup generated by my CMS, I'm using rehype to find images and pass them through eleventy-image, transforming them into full responsive markup.
My experience with the image plugin so far seems representative of other first and third party Eleventy plugins too. There are a lot less of them than with Gatsby, likely down to it being a simpler tool, having a smaller community and less emphasis on plugin development. The plugins I've used so far have all been low-level utilities, exposing filters or helpers that make life easier rather than creating a mess of plugins to join together or adding weight to the page.
Eleventy builds have been fast and reliable, with no strange caching behaviour to contend with. Image processing has added some time to the builds, although there is more I could do to optimise this if it starts to become frustrating.
In terms of front-end performance, navigating between static HTML files feels really fast with Eleventy itself adding no CSS or JavaScript of it's own. I've used Parcel to build my CSS and JavaScript, which is nice and lightweight too.
So far I'm really happy with Eleventy so plan on keeping it as part of my tech stack, it's both enjoyable to work with and produces clean output with a good user experience.
I do now struggle to see myself graviating towards Gatsby for any future projects. It feels like Next.js is the more mature framework for working with React on the server for both small and large projects, and still lets me work how I'd like to work within my codebase. Whereas Eleventy is ideal for a simplier, content-heavy site like a blog where React doesn't add that much value.
That isn't to say that Gatsby doesn't have it's place. It may not be for me, but I can definitely appreciate why it appeals to a lot of people. It provides a lot of functionality and a lot of developer convenience for working with React in a similar way to how jQuery provided a lot of developer convenience for cross browser JavaScript which equally made it very appealing.