This blog post will serve as a guide for those who wish to migrate their website to Gatsby. This was the vetting process we followed at Hasura.io to check if it was a good idea to move our website to Gatsby.
tl;dr: With Gatsby your pages will load extremely fast. You also get automatic SSR for your react app. Moreover, you can leverage Gatsby’s rich plugin ecosystem to build your apps.
Gatsby is a static site generator for React. A Gatsby site gives you client side code splitting and lazy loading of assets out of the box. This means that Gatsby gives the browser a complete page as a single file. All the necessary CSS and images are embedded in the page. Only the CSS really needed for that page is included. Gatsby also performs prefetching. After a page is loaded, it fetches data for all the other pages that are linked on the loaded page. This makes user navigation extremely fast.
A complete list of what you will get with Gatsby can be found here.
Since Gatsby is built over React, the developer experience is the same as developing a React app. So you get automatic SSR for your react app.
Gatsby also has a mature plugin ecosystem. These plugins handle a lot of use cases and can be leveraged in any Gatsby app. Gatsby is also highly customisable and makes it very easy to develop custom plugins.
When is it most suitable to consider Gatsby?
Gatsby is basically just a react app and you can ideally build any webapp on it. To make the most of its features, it is best to use Gatsby if:
- You are comfortable developing in React or if your app is already built on React.
- You require SSR pages for your website.
- Your website content does not change very frequently (once every half hour or so).
Evaluating the effort
Ok, so you have decided that you want to use a static site generator for your web app and have decided to go with Gatsby.
Start off by splitting your app into
- Static pages
- Pages with dynamic content
- Programatically created pages
- Non SSR or client side pages
Let’s take a look at what each of these pages are and how they can be implemented on Gatsby.
Getting these setup in Gatsby is very straightforward. If you are okay with the routes that it provides by default, every component inside the
src/pages directory will be rendered (
/ and every other file at
Pages with dynamic content
These are pages which rely on some external database to load its contents.
To do this in Gatsby, you will have to
- Add this data from the external source into the internal Gatsby data store. This can be done with the help of the
sourceNodesAPI and the
createNodemethod in your
- Access this data from the internal store in your react components using GraphQL APIs.
If this page also shows some data which updates very frequently, you can basically build a “Hybrid” page. You can read about this in their docs. Going with this method, Gatsby will first render your page and then load the React components. Once the React components are loaded in the browser, you can then fetch the data from your APIs.
Programmatically created pages
Sometimes you will have a set of pages which you would want created based on your data. A set of pages showing details about a Product in an e-commerce website is a good example of this. In this case, based on your data (available products) you will render a page for each product.
Programmatically creating pages includes these steps
- If you are dependent on external data, then you need to add the external data to the Gatsby’s internal data store.
- You need to implement the
createPagesAPI in the
gatsby-node.jsfile to programatically create the pages.
- Create your React component for these pages and put the component inside the
Note: If you want custom routes for your static or dynamic pages, you can use the
createPages API and move your component inside
Non SSR or client side pages
These are pages that are not static and should only be rendered on the client side. These include login pages, a console or a dashboard which is dependent on user sessions.
These can be created with the help of the
onCreatePage API in the
gatsby-node.js file. You can read up about this here.
You will also have a few other requirements or configurations that are currently working in your app. The ones mentioned below are the ones that we have with hasura.io
- Webpack configuration
- Pagination for list pages
- Redux for state management
Custom Webpack configuration
Gatsby comes with a default webpack configuration. But you can modify this configuration in your
gatsby-node.js file by exporting the
modifyWebpackConfig function. You can modify the configuration as per the
webpack-configurator configuration. Check here for examples and docs.
In the case of Hasura.io, our requirement was to have support for
.scss files and
bootstrap. This was also quite easily possible in Gatsby.
There is a Gatsby plugin called
gatsby-plugin-sass that can be used to provide support for
.scss files out of the box. You can read the documentation here to include it in your project.
bootstrap, install it by running
npm install --save-dev bootstrap and then include it in your styles with a
Pagination is a very common use-case for listing pages. Handling pagination is also quite straightforward with Gatsby. You can make use of the
gatsby-paginate plugin to get this done easily.
Gatsby works quite well and easily with Redux. The only configuration required is to provide your store and wrapping a component with the
Provider in the
The best way to see this working is to check out the example here.
Routing is provided out of the box by Gatsby. It does this by rendering every component inside the
src/pages directory at the route
For custom routes, you have to export the
createPages function inside the
gatsby-node.js file and then provide the route path and the path of your component to the
createPage method. Usually, these components are placed inside the
Your build and deployment process
Deploying a Gatsby app is as simple as serving static files.
You start with the build process by running
gatsby build and then serve the files in the
public/ directory. You can find instructions to deploy Gatsby on various static site hosts here.
The thing to keep in mind is that every time your data changes, you need to run the build process again and then serve the newly built files. Hence, while considering migrating to a static site generator like Gatsby, you need to account for your current build and deploy process and check how it will fit in with Gatsby’s workflow.
Although porting the features and requirements from our current implementation of hasura.io to Gatsby is possible, there are a few things we are hoping gets better or is figured out before we actually perform this migration:
There are two major ways to handle data updates,
- Setup a cron to rebuild your app every n minutes.
The issue with setting up a cron is that your data updates will lag based on the frequency of your data update and your cron. For existing pages, we can handle this by updating the data from the react component after the page has loaded. But if your data change requires a new page to be generated programmatically, they will not show up immediately.
- Rebuild app for every data change.
Non trivial to setup
You need to setup some form of workflow where you detect data changes and either rebuild on every change or prioritise changes and rebuild only on important updates. Unfortunately, this isn’t something that you will get out of the box and hence will require some time and effort to implement.
Longer build times
As your data keeps increasing, your build times will get longer. Incremental builds are therefore, the need of the hour! Although it is not present in the current version of Gatsby (v1), it is set to come out with the v2 release. So this is just a matter of time.
Incremental builds with Docker
At Hasura, we have a Docker and Kubernetes based deployment process. Utilising the incremental build process of Gatsby will be non trivial. A docker based incremental build process is something that needs to be supported by Gatsby (or maybe we will contribute to Gatsby with a solution).
External Data Source
Currently, if you have an external data source, you need to include it inside Gatsby’s internal data store. You can then access this data using GraphQL APIs from your React components. This process, albeit neat, is a little redundant if you already have an external source which supports GraphQL APIs. You now need to fetch this data during build, convert it to fit Gatsby’s internal store and then specify another GraphQL API to get this data in your React component.
This process can be avoided if Gatsby provides support for GraphQL schema stitching. This will make the experience of developing Gatsby apps with external data sources (which support GraphQL) super awesome. You can conveniently avoid the whole process of retrofitting your data into Gatsby’s internal store and directly query it from your React components.
The Hasura platform provides out of the box GraphQL data APIs and we would like to use them directly. This is also a feature that hopefully is set to come out with the next version (v2) of Gatsby.
Hasura.io migration verdict
Although, Gatsby is awesome, hasura.io migration will have to wait until we have
- A docker based incremental build and deployment process setup.
- GraphQL schema stitching
Having said all of the above, a thing to note is that Gatsby is open source and very modular. It is very easy to add features to it. Moreover, Kyle Mathews (Creator of Gatsby) is open to contributions. So, if you wish to use Gatsby and are reluctant because of a few features, you can very easily implement those features by forking the repo or just contributing to Gatsby.
Psst…. Have you tried deploying a Gatsby web-app on the Hasura platform? It is literally the fastest way in the world for deploying fullstack apps to an HTTPS domain (with just a git push).
Get started with a basic Gatsby project here: https://hasura.io/hub/projects/hasura/react-gatsby
All project boilerplates on the Hasura platform come with a Dockerfile and Kubernetes spec files that you can customize as you wish!