Gatsby is a popular static site generator that can communicate with any backend.
The front-end landscape has exploded in the last three years. Today you have various libraries/front end frameworks like React, Angular, VueJS. You have tightly coupled full stack frameworks NEXT, NUXT etc. Of all these options Gatsby finds a sweet spot with its JAM stack approach. JAMstack is “a modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.”
In this article we will discuss how we can make use of the JAM stack using Gatsby and Drupal. We will also cover the general questions that are generally not answered in the blogs.
There are many todo articles that already explain how to get started with Drupal and Gatsby. I will just link to them here instead of repeating and answer the questions that I had when following them. If you have already made your decision just visit the Setting up Gatsby section.
JAMstack is “a modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.” In a crude analogy you can think of it like the static files deployment that you were doing if you were in software development say a decade ago. This is not entirely true but JAM stack tries to combine the ease of static sites along with the dynamicness provided by APIs.
Javascript : Javascript is used for the client side interactions, better handling of dynamic rendering of elements on the client side and also for interaction with the backend if any. Think AJAX.
APIS : Any interaction with the backend is abstracted into reusable APIs. One more advantage is that in the front end you can make use of your own APIs as well as any third party APIs.
Markup : You will using the Markup or HTML/css for the front end. In JAM stack markup is generally prebuilt at the deploy time.
Gatsby is a static site generator. What this means is that the public folder that is created during the build time will function as a static website. So you can take that folder and deploy it on any server with Apache or nginx like server to serve the requests. For example if you use the default starter kit of Gatsby communicating with Drupal backend, you only need the backend to be up during the build time. Once your build is done, you can down your Drupal server and just deploy the public folder generated during the build. What this means is that your Gatsby site will communicate with your Drupal backend during the build time, fetch all the details necessary and create static files for all the paths that will be present on your site.
Think of Gatsby as a state-machine. The state consists of the code changes you make and also the data you save in your database. So whenever there is a change in the code or the data in the database, you need to rebuild it for the latest state. For code changes it is easier to trigger the build. For the changes in database it is a little bit difficult. But you can make use of web hooks to trigger these builds. But the question is how frequently do you trigger your builds? Let us say that you can stay with some stale data, then you can have builds every few hours. This might be suitable for blogs where if the content is refreshed every couple of hours/days it should be sufficient. But if your site has lot of user interactions then frequent rebuilds might be a pain and it will also add load on the server. In such scenarios it would make sense to keep the content that changes less frequently in a backend like Drupal and for the content that changes frequently(like comments) it might be better to off load to a third party service(like Disqus for comments).
If you would like to have control of all your data(both that changes less frequently and more frequently) then it might make sense to do the Gatsby build for content that changes less frequently, then add React components that interact with live API calls for content that changes more frequently. Since Gatsby is built on React, you can stick to your standard API calls in componenentDidMount and then render the results in render function.
If you are not sure whether to use Gatsby for the whole of your site, then this approach can be good. For example let us say that you have a website that has many functionalities including blog, you can just transfer the client facing blog functionality of your website to Gatsby. In your apache/nginx config just make sure that only www.example.com/blog is handled by your Gatsby front end and all other parts are handled by Drupal.
One simple approach I took was to make sure that I have Drupal backend at backend.example.com and front end at gatsby.example.com
In my gatsby-node.js I added a rule like
result.data.allNodePage.edges.forEach(({ node }) => {
createPage({
path: node.path.alias,
component: staticPageTemplate,
context: {
slug: node.path.alias,
},
})
})
This makes sure that even in the gatsby front end I can use the path set in the backend. So for example backend.example.com/blog/firstblog to gatsby.example.com/blog/firstblog This way it was easier for me to map and check the missing pages from the sitemap.xml as well.
Gatsby comes with a default SSR settings. What it means is that API calls to your data sources are made at the build time. So all the pages are server side rendered. Once you are done with a build you can pretty much shut down your backend unless you have any real time API calls that you need to do from your Gatsby app.
By default Gatsby plays well for read only kind of websites. But there is nothing that stops you from creating forms and authenticated user flows as it internally used React. Connecting Gatsby with Redux might be good for authenticated flows. Checkout https://medium.freecodecamp.org/how-to-get-started-with-gatsby-2-and-redux-ae1c543571ca for Gatsby with Reduct integration. If you want to add authentication to your Gatsby sites checkout https://www.gatsbyjs.org/blog/2019-03-21-add-auth0-to-gatsby-livestream/#authentication-in-gatsby
In Drupal jsonapi is a popular module. There is also a graphql module. But if you are using https://www.gatsbyjs.org/packages/gatsby-source-drupal/ plugin you will observe that on the Drupal end you just enable the jsonapi module thats all. What is happening is that the the GatsbySourceDrupal plugin is taking care of the jsonapi output and converting it to graphql compliant structure so that you can actually use graphql queries to access your data in Drupal. You are generally asked to enable the jsonapi access to all user. Be careful as you might be exposing some confidential data that is not intended. Do check these out before deploying in live.
Gatsby is a great tool. It makes starting with REACT and Drupal so easy. It is also highly configurable and customisable. But it can still be overwhelming for Drupal developers who have not worked with Frontend frameworks earlier. Thanks to open source we have other alternatives.
Tome is another interesting project that generates static sites for Drupal 8 quickly and without needing to know the new frontend libraries and tools.
In https://twitter.com/DrupalSAM’s own words
It’s important for me to make Tome more accessible to less technical users. Anyone that can make a Drupal site should be able to make a static site without learning a completely different toolset and programming language.
I think this is a great goal and will help Drupal community immensely. Once people realise the advantage of JAM architecture I am sure most of the blog like sites will default to static sites :)
If you don’t trust me, just checkout the video in below tweet to realise how easy it is to create static sites with Tome.
body[data-twttr-rendered="true"] {background-color: transparent;}.twitter-tweet {margin: auto !important;}
Working on an in-site preview feature for Tome - soon you'll be able to download, generate, and preview your Drupal static site without touching the command line. 🖱️✌️ https://t.co/qmXYMufgkG
function notifyResize(height) {height = height ? height : document.documentElement.offsetHeight; var resized = false; if (window.donkey && donkey.resize) {donkey.resize(height); resized = true;}if (parent && parent._resizeIframe) {var obj = {iframe: window.frameElement, height: height}; parent._resizeIframe(obj); resized = true;}if (window.location && window.location.hash === "#amp=1" && window.parent && window.parent.postMessage) {window.parent.postMessage({sentinel: "amp", type: "embed-size", height: height}, "*");}if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.resize) {window.webkit.messageHandlers.resize.postMessage(height); resized = true;}return resized;}twttr.events.bind('rendered', function (event) {notifyResize();}); twttr.events.bind('resize', function (event) {notifyResize();});if (parent && parent._resizeIframe) {var maxWidth = parseInt(window.frameElement.getAttribute("width")); if ( 500 < maxWidth) {window.frameElement.setAttribute("width", "500");}}
As with most answers to the technical questions, that answer is “It depends” :P
But here is the thumb rule I use.
Before setting up Gatsby I would recommend going through the following two videos. They give you a high level insights and should be sufficient to get you started quickly.
If you would like to understand the details of how Gatsby works and how to customise it for Drupal, you can check out this blog by Ryan Bateman
Tutorial: GatsbyJS for Drupalers; or, How to JAMStack-ify your Drupal Site with GatsbyJS
I hope this answers some of your questions before shifting to Decoupled Drupal site or deciding on the front end frameworks for your Drupal API backend.
If you have any questions that I am not able to answer just let me know about them in comments. We can explore them together and share our notes for mutual benefit. Let us make this as a repository for all the commonly asked Questions by Drupallers regarding headless option.