Day 195: Gatsby vs. Next.js

For the past year, I’ve been using Gatsby to build all of my websites. My personal site, the marketing sites of Intention, Hide Feed, Hide Likes, and other projects like Just One Earth are all built using Gatsby. I’ve created a custom Gatsby starter for new sites, reported bugs, fixed some of them, built a custom plugin, and have caught enough typos on the documentation site to have received a free t-shirt:

Been wearing this baby to sleep every night since I got it which is pretty weird because I’m generally allergic to tech swag and other branded merch. (My wardrobe is like 100% Uniqlo.)

Been wearing this baby to sleep every night since I got it which is pretty weird because I'm generally allergic to tech swag and other branded merch. (My wardrobe is like 100% Uniqlo.)

The point is, I’m a teensy bit invested in the Gatsby ecosystem at this point.

But I’ve also seen a lot of talk about Next.js on Twitter (it’s probably because I follow @rauchg, the CEO of Vercel, whose socket.io library I used almost a decade ago!) so I figured I’d try it out before deciding what to use to build the website for Browserflow.

My biases going in:

  • I’m lazy and would rather not have to learn another thing
  • But if Next.js were clearly better, I’d rather switch now rather than later

Even though I’ve put a lot of time into learning Gatsby, I’m not opposed to switching — the engineering purist in me just wants a clear winner so that I know what to invest in going forward.

By the way, there are other considerations when deciding between technologies like the ecosystem, community, culture, etc. but there isn’t a significant difference between Gatsby and Next.js in those regards — they’re both quite popular. This post will focus purely on using them from a technical perspective.

I decided to live-tweet the experience of going through the basic tutorial, which is an exercise I probably won’t repeat given that it took like 10x longer to get through the tutorial. By trying to make sure I wasn’t misrepresenting the current state of Gatsby, I was constantly referencing Gatsby’s docs and it felt like I was going through Gatsby’s tutorial as well all over again at the same time.

Thankfully, the tutorial wasn’t too long, and now that I’ve gotten a taste of Next.js, I figured I’d use today’s post to share some impressions of Gatsby vs. Next.js:

  • Next.js is much easier to use
  • Gatsby makes it easier to optimize performance (but for my projects, it probably doesn’t matter)

Let’s look at some examples, shall we?

📄 Example: Creating dynamic pages

Let’s say that you’re building a blog and want to have dynamic pages (e.g. /posts/gatsby-vs-next).

  • Next.js: Name your file [id].js and export a function that returns the possible IDs.
  • Gatsby: Use a special config file called gatsby-node.js to hook into Gatsby’s bootstrap sequence so that you can use Gatsby’s Node APIs like onCreateNode and createPages.

If Gatsby’s way sounds complicated, that’s because it is. It’s also ickier that the routes have to be generated in a configuration file rather than in the file it pertains to.

♻️ Example: Fetching data

Say you want to fetch some Markdown files stored on disk to generate your blog posts.

  • Next.js: Use standard Node.js APIs to read the files from disk and process the files using markdown libraries (gray-matter, remark, remark-html) to get the data you need.
  • Gatsby: First, install a source plugin called gatsby-source-filesystem and add it to gatsby-config.js to tell Gatsby how to find the files, then install a transformer plugin called gatsby-transformer-remark and add that to gatsby-config.js so Gatsby knows how to process the Markdown files, then write a GraphQL query to get all the files and map them to pages inside gatsby-node.js, then inside the template, you use a GraphQL query to get the data and render it in a component.

Easy, peasy, lemon squeezy, right?

Why is Gatsby so much more complicated?

It’s because its entire data layer is built on GraphQL. All that extra work to source and transform your data is required to get it into a format that’s workable with GraphQL. To be fair, you can certainly use Gatsby without GraphQL, but if you go that route, you’re not really using Gatsby as it’s designed to be used.

This is where my experience is too limited to make a blanket judgment on whether the overhead of GraphQL and jumping through a bunch of hoops to make it work is “worth it”. Perhaps on massive sites with tons of data sources, being able to query everything using GraphQL is a life-saver.

Here’s what I do know from my experience: For the projects I’ve worked on, the only meaningful benefit of using Gatsby’s GraphQL setup has been easily optimizing images.

Once you’re running all your data through the GraphQL data layer, Gatsby makes it trivial to optimize your images to get things like lazy loading, generating multiple image sizes for different devices, and “blurring up” your images.

Having all this done automatically is freaking awesome. There’s a reason why Gatsby sites are wicked fast, even with a ton of images. Next.js doesn’t provide any optimizations like this as far as I know.

But there’s a tradeoff being made here: Is the extra complexity worth it?

Going through Next.js’s tutorial felt like a breath of fresh air because of how straightforward it was. It showed me just how much (unnecessary, in my case) complexity I’d simply gotten used to when working on Gatsby sites.

Next.js’s simplicity is appealing enough that I’m going to build Browserflow’s website on it, and if that goes well, I’ll probably make the switch to using it as my default framework. I’ll miss all of Gatsby’s magic when it comes to performance optimizations, but to be honest, my projects are small enough that it probably doesn’t matter. What does matter, especially as a solo developer, is how maintainable those projects are, and being able to leverage the simplicity of Next.js for both static sites as well as server-rendered sites seems way more promising that trying to remember the details of how source and transformer plugins and special lifecycle APIs work.

Given that I’ve only messed around with Next.js for a few hours, it’s possible that I discover that there other relevant factors that I’ve failed to consider here (e.g. perhaps I’m unable to find equivalent libraries for Gatsby plugins I depend on), but for now, it’s time to dive more deeply into Next.js!