Gatsby.JS Live Previews with Drupal

May 29, 2021 — Sergiu Nagailic (Nikro)
Gatsby.JS Live Previews with Drupal
Tags:#Drupal#Gatsby.JS#Planet
Categories:#General
ABOUT THE AUTHOR
Sergiu Nagailic (Nikro) — CTO & Co-founder at HumanFace Tech
Hands-on technical leader with 16+ years across CTO, tech-lead, and product architecture roles. Specializes in AI product delivery, RAG and agentic systems, and technical leadership.
Connect: Twitter | GitHub | LinkedIn | HumanFace Tech

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: 

...
 "scripts": {
    ...
    "preview": "gatsby develop -- --host 'preview.YOURDOMAIN.com --port 8000",
    ...
  },
…

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:

[Unit]
Description=preview_gatsby.js - Preview for YOUR DOMAIN.
Documentation=https://YOURDOMAIN.com
After=network.target

[Service]
Environment=NODE_PORT=8000
Environment=ENABLE_GATSBY_REFRESH_ENDPOINT=1
Type=simple
User=ubuntu
ExecStart=/usr/bin/npm --prefix /var/www/PATH/app run preview
Restart=on-failure

[Install]
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:

server {
        listen 80;
        server_name preview.YOURDOMAIN.com

        root                    /var/www;
        index                   index.html index.htm;
        access_log              /var/log/nginx/proxy.access.log;
        error_log               /var/log/nginx/proxy.error.log;
        include                 mime.types;
        default_type            application/octet-stream;
        sendfile                on;
        keepalive_timeout       300;
        client_max_body_size    256M;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_read_timeout    120;

        location / {
                proxy_pass              http://localhost:8000;
                proxy_buffer_size       32k;
                proxy_buffers           8 16k;
                proxy_read_timeout      90;
                proxy_connect_timeout   60s;
                proxy_send_timeout      90;
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Proto $scheme;
    }
}

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!
 

Related Articles:

  • From Drupal 7 to Drupal 8 + Gatsby.JS (Part 1) — Running a self-hosted blog has its challenges - and I bumped into some of those eventually. Why and how I have migrated from a Drupal 7 to a headless Drupal 8 + Gatsby.JS as the front.
  • Deep-dive into Drupal 8 + Gatsby.JS (Part 2) — Welcome to 2nd part - hands-on or deep-dive into Drupal 8 + Gatsby.JS. Don’t treat this article as a tutorial - but hopefully, my experience will be useful for your journey.