Gatsby.JS Live Previews with Drupal

Professional Article
May 29, 2021

If you have a decoupled Gatsby + Drupal site, then you’re probably annoyed waiting for 5-10 minutes for the build to finish - to see how your CMS changes landed on the actual website. There’s a better way - Gatsby Previews (took me a while to look into it). With Live Previews you can view your new and edited content instantly.

How to enable the Preview

There’s this neat contrib module - called “Gatsby” - https://www.drupal.org/project/gatsby 

It consists of 4 different sub-modules:

  • Gatsby - Improves integration with GatsbyJS including adding Live Preview and Incremental Builds;
  • Gatsby Fast Builds - Enables faster Gatsby development builds by only downloading content that has changed;
  • Gatsby JSON:API Extras - Adds additional enhancers when using Gatsby with JSON:API;
  • Gatsby JSON:API Instant Preview and Incremental Builds - Enables a faster preview experience and incremental builds support when using JSON:API and gatsby-source-drupal.

I usually use all these, except for “Gatsby JSON:API Extras” - this one alters the GraphQL output and it doesn’t always suit me - because I already built my GraphQL queries and I don’t want to alter those.

I’ll consider that you want to enable a special sub-domain: preview, i.e. preview.nikro.me, or, preview.YOURDOMAIN.com.

Once you enable all these - head to: admin/config/services/gatsby/settings

Here you specify the following (example):

  • Gatsby Preview Server URL: http://preview.YOURDOMIAN.com:8000
  • Incremental Build Server Callback Hook(s): http://preview.YOURDOMIAN.com:8000/__refresh 
  • Entity types to send to Gatsby Preview and Build Server: go ahead and check some entities that you want.

Make it as a running Service

I assume you run your builds via some CI/CD process (i.e. CircleCI or Netlify) - so you’ll need to make sure that your Drupal’s server (the one you use for editing content) has also node installed, gatsby, and all the node packages (dependencies) - basically make sure it can run: build or develop.

Edit package.json - add this bit: 

  1. ...
  2.  "scripts": {
  3.     ...
  4.     "preview": "gatsby develop -- --host 'preview.YOURDOMAIN.com --port 8000",
  5.     ...
  6.   },

This will allow us to run ‘gatsby develop’ by running: npm run preview.

If you’re running an Ubuntu machine, that has systemd - create a file here:
/lib/systemd/system/preview_gatsby.service

Here’s a template:

  1. [Unit]
  2. Description=preview_gatsby.js - Preview for YOUR DOMAIN.
  3. Documentation=https://YOURDOMAIN.com
  4. After=network.target
  5.  
  6. [Service]
  7. Environment=NODE_PORT=8000
  8. Environment=ENABLE_GATSBY_REFRESH_ENDPOINT=1
  9. Type=simple
  10. User=ubuntu
  11. ExecStart=/usr/bin/npm --prefix /var/www/PATH/app run preview
  12. Restart=on-failure
  13.  
  14. [Install]
  15. WantedBy=multi-user.target

Here - make sure to change the YOURDOMAIN and the PATH towards your app. The important line here is Environment=ENABLE_GATSBY_REFRESH_ENDPOINT=1 this is what will expose the /__refresh hook and enable our develop - act as a preview service.

Once you’re done with this, run: sudo service preview_gatsby start - if everything goes fine - you should see no errors. You can check for errors (🐛) by running: systemctl status preview_gatsby.service - green is good, red is bad 😀

All good, even though we’re running the gatsby preview and the modules are installed and configured - the missing piece is nginx acting as a proxy. Create a virtual-host, in example: /etc/nginx/sites-availabe/preview.YOURDOMAIN.com with similar contents:

  1.         listen 80;
  2.         server_name preview.YOURDOMAIN.com
  3.  
  4.         root                    /var/www;
  5.         index                   index.html index.htm;
  6.         access_log              /var/log/nginx/proxy.access.log;
  7.         error_log               /var/log/nginx/proxy.error.log;
  8.         include                 mime.types;
  9.         default_type            application/octet-stream;
  10.         sendfile                on;
  11.         keepalive_timeout       300;
  12.         client_max_body_size    256M;
  13.         fastcgi_buffers 16 16k;
  14.         fastcgi_buffer_size 32k;
  15.         fastcgi_read_timeout    120;
  16.  
  17.         location / {
  18.                 proxy_pass              http://localhost:8000;
  19.                 proxy_buffer_size       32k;
  20.                 proxy_buffers           8 16k;
  21.                 proxy_read_timeout      90;
  22.                 proxy_connect_timeout   60s;
  23.                 proxy_send_timeout      90;
  24.                 proxy_set_header        Host $host;
  25.                 proxy_set_header        X-Real-IP $remote_addr;
  26.                 proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  27.                 proxy_set_header        X-Forwarded-Proto $scheme;
  28.     }
  29. }

And then create a symlink in /etc/nginx/sites-enabled and run a test: sudo nginx -t 

Now you’ll have traffic proxied from :80 -> :8000 (preview) and things should work. Now you might be asking - why did we specify to Drupal the :8000 port? Through trial-and-error I came to this conclusion - it’s because Drupal sits on the same machine 💻 (in my case), so it doesn’t like to go through the nginx proxy, and triggers the hook directly.

Securing the Preview

As you might have noticed - I used http and not https, nor I have specified Gatsby Secret Key - in the configuration of the Gatsby module in Drupal. 

To make things the right way - you’d want your Nginx to listen to 443 instead of 80 -> install let’s encrypt and make sure everything’s secured.

What about that secret? 🔒 Here you can see the example - secret can be used on both sides:

  • In Drupal - you specify the random string.
  • In Gatsby - where you specify the Drupal source (in gatsby-config.js) - you specify the same string.

This adds a layer of protection for previews between the two.

Test and have fun!

I add / edit content once a month or so - and when I do, I start the preview service, get my stuff done and then shut it down (for security purposes, greener planet and all that) - I recommend you do the same 🌍

Have fun!

Comments:

Feel free to ask any question / or share any suggestion!