Background

I was building a pretty large static website using Gatsby -- it has about 175k pages. Initially it took hours to build (from static JSON data), but with some help from some core contributors, I was able to bring the build time to ~13 minutes. But the size of the build data (public directory) came to 2.8GB roughly. It's a known fact that Gatsby inlines all the CSS styles in each HTML page to improve performance. While it's really good, it came with a huge cost for my site. After changing Gatsby's default behaviour of inlining styles and making it link to external CSS file, the bundle size came to ~1.4GB.

With this setup, I thought it'd be easier to deploy the site while I still do the development. My first choice was to deploy it to Netlify as the CI/CD setup is really easy. Unfortunately, Netlify couldn't build the site -- it was always timing out after like 10 minutes. My next preference was ZEIT Now and it too failed to build & deploy the site. After contact their support, I got to know that they don't support such large sites in free tier. Maximum number of files that's supported in free tier is 10k 🤷‍♂️

Solution

A friend suggested that he uses Firebase deploy his Gatsby site. Though I've played around with Firebase earlier, I've not tried their hosting service.

It turned out that Firebase doesn't have a direct Git(Hub) integration like Netlify / ZEIT Now where you can just link your repository and configure the command to build & deploy your site. So it's going to be a "manual" CI/CD setup and I thought why not try GitHub Actions to automate the site deployment.

After digging through GitHub Actions documentation and some of the examples, I got the continuous deployment working 🎉. It takes about 15 minutes to build the site and a little more than hour to deploy the site to Firebase hosting, but thankfully it doesn't error out.

Here's the gist of my Actions workflow:

name: CI

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Setup Node.js for use with actions
        uses: actions/setup-node@v1.1.0
      - uses: actions/checkout@v2
      - name: Clean install dependencies and build
        run: |
          npm ci
          npm run build
      - name: Install firebase-tools globally 🤷‍♂️
        run: npm install -g firebase-tools
      - name: Deploy to Firebase
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
        run: firebase deploy --token $FIREBASE_TOKEN

That's probably not the best way to write the GitHub Action. I'm not sure if it's recommended to split these steps into their own jobs, but this works for me for now.

For this to work, you should have setup your repo as a Firebase project. Gatsby has a good document on how to get this working -- https://www.gatsbyjs.org/docs/deploying-to-firebase/

Once you have done as described in the documentation, you've commit the generated firebase.json and .firebaserc files to your git repository.

Then you've to generate a Firebase token for the CI system. To do this, run:

firebase login:ci

This will print your token in terminal. Copy this token and add it to GitHub secrets with the name FIREBASE_TOKEN using this guide.

Here's the example repo -- https://github.com/tsriram/ifsc