When should you use Gatsby?
Gatsby.js is one of the most popular frontend frameworks currently and a huge buzzword in frontend web development. For anyone who isn’t aware of Gatsby.js yet, it is a frontend framework that allows you to develop a statically generated website using React. This allows you to get the development benefits of React, and also get the SEO, page load, etc. benefits of a statically generated website. Sounds great right? Well not so fast. I believe many people are too quick to reach for Gatsby when starting a new frontend application, and many people are using it in places where they really shouldn’t. I too was a victim of this thinking, and started a project with Gatsby that I really shouldn’t have (more on this in a bit). I have also heard of others including companies using Gatsby either when they could probably benefit better from another framework. Don’t get me wrong though I do really like Gatsby, this site is built using Gatsby! When Gatsby is used correctly it can be great. In this post I will try to go over some of the reasons and situations you should use Gatsby, but also outline some situations where you should not and you are better off gravitating to another framework like Next.js. These lists and ideas are definitely not exhaustive or the only opinion, but I think they are a good rule of thumb to go by. I may update this page as new things come to light from my and others experience.
Recently I needed to create an admin interface at work. I had started working with Gatsby when creating this blog and had really loved the experience. The idea that I can code in React and use all the libraries and techniques I’m used to, while also getting the benefits of a statically generated website is awesome. The plugin system for Gatsby is also very cool, and allows you to easily add in Gatsby plugins to get the functionality you would normally have to do a lot more setup for. I have experience with plain React and Create React App(CRA) as well as server side rendered(SSR) React using Next.js, but my first thought was to reach for Gatsby again to create this admin interface for a backend API that already had been started. This was a bad choice for a few reasons.
Let me start by outlining some of the basic requirements for this admin interface.
- Only authenticated users should be able to access any part of the application besides the login, forgot password, and reset password pages.
- Once you’ve logged in, there is minimal static content on the pages besides the navigation bar.
- Almost all of the data on the page comes at render time and can be updated by user actions.
- There are dynamic routes in the application for accessing resources that can be created in app.
- SEO is not necessary because we only want our users to use this application, and therefore all bots should be disallowed.
Just from these few simple requirements I’m sure a lot of people will quickly be able to tell that Gatsby was not the right choice, but for those who can’t let me outline why Gatsby wasn’t a good choice. The first requirement requires me to make almost every single route in the application a client side only route. This means these routes are not statically generated and do not have corresponding index.html files. The third requirement further outlines this problem in that most of the data on the page comes at render time and is generated by an API and not during the build phase of the Gatsby application. Furthermore, user’s can update and create resources therefore creating more content for application which can’t be statically generated at build time. The last major reason that Gatsby was most likely not the best choice for this application was because I do not need any SEO benefits.
I’ll go into more of the reasons when you shouldn’t pick Gatsby later on, so I won’t dwell on these too much for now. Basically all of these requirements should have led me to look at other frameworks or templates for my application. If I am being honest with myself, I had realized some of these drawbacks before starting the application and realized Gatsby may not be the best option. However, I thought it over and came to the conclusion that using Gatsby would be better than using CRA (normal react setup) or a framework like Next.js. My thought process behind this is I know a Gatsby app is still faster to load in the browser than a normal react application even if I’m not getting all the benefits of it being statically generated. And I knew deploying a Gatsby application on AWS (where we host all of our applications), is easier to do than deploying a Next.js application. This is because Next.js needs a server since it’s SSR, and therefore you either need to deploy a running server application on AWS and maintain/monitor it or you have to do some cleverness to get it to run serverless using Lambdas. Gatsby (and normal react applications) have a build process that results in a bundle or set of files that you can just put into an S3 bucket and put Cloudfront in front of it and be done. So I stayed with Gatsby for the faster load in the browser and the ease to deploy it. However, I eventually ran into a problem that would cause me to have to give up on using Gatsby for this application.
While developing the application everything seemed to be going great. We are a small startup and I was developing as well as doing QA on it myself. So I would develop locally, write tests, check it locally, and then deploy to staging and quickly test the app there as well. Everything seemed to be going well, until the app had gotten to a good minimal place to be used by others and I started giving others access to staging to test and use it. This is when I started running more rigorous tests myself on staging to make sure everything was working as expected. I ran through all the basic functionality once and it seemed to be working great. However, I did some refreshes and realized something weird going on with the styling. After refreshing and checking the auth token in local storage, it went from the login page to the first authenticated route but the page was much smaller and located in a smaller div that made a box in the center of the page. After some debugging I realized it was putting the whole React component of the authenticated client side route, into the login page root div element. This caused the whole page to be rendered within the login box and be unusable. I checked this over and over locally in multiple scenarios and was unable to replicate it. It only existed in the staging environment. So I turned to the Gatsby issues to see if others were experiencing a similar issue. There were lots of people with CSS issues where they weren’t being applied correctly or they were mixing up classes. Originally I thought it might be this, but then I took a look at the Gatsby client side route example to see if I was doing anything wrong in the code. I couldn’t find anything different from my application, so I took a look at the hosted example (which has since been taken down). I noticed in this example that if I went to any page that wasn’t the home page and refreshed, that the styles from the home page were applied to the refreshed page instead of the appropriate styles because the root dom element was updated incorrectly. This seemed to be very similar if not the exact problem I was facing with my application which was basically all client side routes. So I opened up an issue on Gatsby’s github here, and have still yet to hear anything from anyone.
I couldn’t just wait for this problem to be figured out or try to solve it myself (without knowing Gatsby’s codebase), because who knows how long it has existed and how long it would take to solve. I needed to move quickly because this was a necessary part of our software architecture, and we needed to continue development. So begrudging thel solution I chose was to rewrite the application not using Gatsby. So I chose to rewrite the application using Next.js, which I also had used before and knew the file structure was very similar to Gatsby. The main differences to convert the application was to remove all the Gatsby methods and use built in Next.js methods instead, replace all the Gatsby plugin functionality that we needed, and setup the tests to work in the new project. The final difference would be getting the application deployed, which as stated previously required deploying a running server. All in all moving the app’s components and pages over, replacing the Gatsby methods with Next methods, and getting the app to run took about a day. Then getting the tests to run took about another day or so, and deploying the application took about half a day. However, the deployment went fairly quickly because we use Kubernetes, and all we had to do was set up our docker container and repo, our deployment files, and our Kubernetes cluster to deploy this new application. If I had gone with my gut and thought through it more, I could have started in Next.js from the beginning and none of this would have happened. Therefore, I thought it would be nice to outline my problem as well as some of the tell tell signs of when to/not to use Gatsby.
Disclaimer: All of this could have been found earlier if I had done more rigorous testing on staging from the beginning and is something I would normally do, but working alone and for a very small startup when trying to move fast I had forgone this more rigorous testing. So remember always rigorously test on staging.
When you Should Use Gatsby
First let’s talk about some of the great places you should use Gatsby.
- For simple personal websites with a lot of content that doesn’t change too often.
- Blogs (like this one!) which can be generated from markdown or are connected to a CMS and use GraphQL to build all the pages during build time.
- Simple ecommerce sites with a limited set of items that will not continue to grow much over time.
- Marketing websites with simple content or CMS backends that use GraphQL to build the pages.
- Landing pages
- Business websites
- Any site where all or almost all the content is part of a CMS. One thing to note is in order to get the most out of Gatsby it is important to use GraphQL to generate the pages at build time.
While this list is definitely not exhausted (and may be added to), I think these are some of the base cases when you should use Gatsby. I would say one major thing to note when Gatsby should be used is when you know what information is going to be on all or most of the pages at build time and you can easily/quickly rebuild the pages when something is added or changed. I say easily/quickly rebuild the pages because all though in some cases you may know what all of the pages are at build time and what will be on them, the larger your site grows the longer the build will take and the more you should think about not using Gatsby.
When you Shouldn’t Use Gatsby
Now let’s discuss some of the times where you probably shouldn’t use Gatsby.
- Applications that are mostly behind authentication that can’t show data until the user is logged in (like my example above). If the authenticated pages are mostly static for some reason, then it might still be better to use Gatsby. But if the data on the pages changes per user then it is probably best not to use Gatsby.
- Sites with a lot of dynamically generated routes, because you won’t get the benefits of statically generated pages if you don’t know them at build time
- Complex sites (like some large ecommerce sites), that are constantly adding new pages and content because these will quickly grow and have very large build times. Although a lot of ecommerce sites can use and do use statically generated sites, if build time becomes a problem it is most likely time to move away from statically generated sites like Gatsby.
- Sites where most pages don’t get page data until the page is rendered in the browser. You will not get you statically generated page benefits if most of your data comes after the page is rendered
- Sites with CMS’s that change a lot. This also may not be an always case, but if your site has a frequently updated CMS then Gatsby may not be a good option because the build step will slow down changes. Also if your site has a CMS but you don’t use GraphQL to build the pages, then you probably aren’t using Gatsby right and should look at another solution.
I would say two general rules on when you shouldn’t use gatsby are 1) When the site has a lot of dynamic or constantly changing pages/data that doesn’t remain constant 2) or when build times will grow exponentially over time and limit your deployment speed.
There are a number of alternative approaches you can use instead of Gatsby and when you should use them depends on your use case. There is always the general Create React App (Vanilla React) approach which is the simplest approach. You can SSR parts of your app or all of your app which will get you closer to if not all of Gatsby’s benefits. You can do this by either implementing SSR in your Vanilla React application yourself, or if you have the luxury/freedom of starting an app from scratch you can use a framework like Next.js. Next.js is a SSR framework for React very similar to Gatsby but it allows you to better handle more complicated applications that are sure to grow or have a lot of dynamic content. When Gatsby isn’t the best choice, there is a very good chance that Next.js will be a good alternative. Next.js allows you to make requests server side and then render server side which will speed up your applications load time and initial page render in the browser as well as give you SEO benefits, among many other benefits. I do not see Gatsby and Next as battling frameworks but instead as frameworks for different use cases, and I think it is important to note that. Once again this is not an exhaustive list of alternatives but if you are already familiar with React I think they are worth knowing about. I hope this post helps others avoid the problem I encountered, as well as bring some awareness to the different use cases and solutions available.