Four days, four languages, four frameworks, Day 3: GatsbyJS—the React-based static site generator

28 Feb 2019

It’s day three of our four-part series of posts about running Static Site Generators (SSGs) and alternative Content Management Systems on Platform.sh. Today, we’re looking at GatsbyJS, an SSG publishing framework built on top of React Facebook’s Javascript library. What makes Gatsby unique and interesting is that it’s written as a Progressive Web App (PWA).

Gatsby and other PWAs use a combination of client-side (Javascript) and server-side components, which can be both static assets and dynamic APIs. This gets to our third, three-letter-acronym: JAM or JAMstack—an architecture built on client-side Javascript, APIs, and Markup, as opposed to the LAMP (Linux, Apache, MySQL, PHP) server-side stack we know so well from Drupal, WordPress, and so on.

While Gatsby uses a different language (Javascript) and server-side framework (Node) than the other SSGs we’re demonstrating, setting it up on Platform.sh is very similar to how we ran Hugo, the Go-based SSG.

Let’s run GatsbyJS on Platform.sh

We’ll start as we have before with a local version of our application. Since we’re starting from scratch, we need a few prerequisites installed on our machine. If you have an existing Gatsby app, you can skip ahead. You can also download a ready-to-run copy of a Gatsby project for Platform.sh, if that’s more your speed.

1. Set up your local machine

You’ll need four tools to deploy your Gatsby site on Platform.sh:

For each of these tools, please refer to their own install pages.

2. Bootstrap your GatsbyJS project

You need to create a new GatsbyJS folder from a template:

$ npx gatsby new gatsby-hello https://github.com/gatsbyjs/gatsby-starter-blog
npx: installed 1384 in 33.248s
info Creating new site from git: https://github.com/gatsbyjs/gatsby-starter-blog.git
Cloning into 'gatsby-hello'...

...... (Lots of output here)

Initialized empty Git repository in /media/psh/customers/gatsby-hello/.git/
info Create initial git commit in gatsby-hello

You can now run the local development server:

$ cd gatsby-hello && npm run develop

> gatsby-starter-blog@0.1.0 develop /media/psh/customers/gatsby-hello
> gatsby develop

... (Lots of output here)

You can now view Gatsby-starter-blog in the browser.

  http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema.

  http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use npm run build.

ℹ 「wdm」:
ℹ 「wdm」: Compiled successfully.

Browse http://localhost:8000/ to check that everything is working as expected.

The npx template already creates a basic Git repository:

$ git log
commit cd34e2366e6c28de7e0db53b527d6d4ddb1b7952 (HEAD -> master)
Author: Guillaume Moigneu <***@platform.sh>
Date:   Mon Feb 18 12:33:26 2019 +0100

    Initial commit from Gatsby: (https://github.com/gatsbyjs/gatsby-starter-blog.git)

3. Create your Platform.sh project

Create a Platform.sh project by signing to a trial account or log in to your account.

Select a Standard project, then choose the region you want your project to be hosted in.

Review and validate. You can now access your newly provisioned project. On the wizard, click Git remote and copy it.

Add the remote to your local project:

git remote add platform <project ID>@git.<region>.platform.sh:<project ID>.git

Don’t push anything for now. You still need to add the Platform.sh configuration.

4. Set up the .platform.app.yaml configuration

Platform.sh relies on yaml configurations to configure the different containers to deploy. Create the .platform.app.yaml file at the root of your project, and add the following code:

# .platform.app.yaml

# The name of this application, which must be unique within a project.
name: 'gatsbyjs'

# The type key specifies the language and version for your application.
type: 'nodejs:8.9'

# The hooks that will be triggered when the package is deployed.
hooks:
    # Build hooks can modify the application files on disk but not access any services like databases.
    build: |
      npm run build

# The size of the persistent disk of the application (in MB).
disk: 256

# The configuration of the application when it's exposed to the web.
web:
    commands:
        start: sleep infinity
    locations:
        '/':
            # The public directory of the application relative to its root.
            root: 'public'
            index: ['index.html']
            scripts: false
            allow: true

The web section is nearly identical to the Hugo version. Really, serving any static site on Platform.sh is the same at runtime. The build hook is a bit simpler in this case as it need only run npm run build to compile Gatsby.

Because the container type is NodeJS, and the build flavor is left at the default, Platform.sh will automatically run npm install before the build hook automatically to ensure all dependencies are available.

We need also two other files: routes.yaml and services.yaml. services.yaml is used to configure additional services like databases, so we don’t need it for that project. Just create the file:

mkdir .platform
touch services.yaml

Add routes.yaml in the .platform folder, and add the following configuration:

"https://{default}/":
  type: upstream
  upstream: "gatsbyjs:http"

This file tells the Platform.sh router to direct all incoming requests to our gatsbyjs container. Commit these new files:

git add .platform.app.yaml .platform
git commit -m "Add platform.sh configuration"

5. Test and deploy

You’re now ready to deploy the project on Platform.sh. Push the repository to the new remote:

git push platform master

Platform.sh will then build and deploy your Gatsby application, with the following output:

```sh Counting objects: 44, done. Delta compression using up to 4 threads. Compressing objects: 100% (38/38), done. Writing objects: 100% (44/44), 1.04 MiB | 16.98 MiB/s, done. Total 44 (delta 2), reused 0 (delta 0) Validating submodules Validating configuration files Building application 'gatsbyjs' (runtime type: nodejs:8.9, tree: fafb3d4) Generating runtime configuration. Building a NodeJS application, let's make it fly. Found a `package.json`, installing dependencies. > sharp@0.21.3 install node_modules/sharp > (node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy) ... up to date in 14.102s success open and validate gatsby-configs — 0.009 s success load plugins — 0.325 s success onPreInit — 0.895 s success delete html and css files from previous builds — 0.096 s success initialize cache — 0.016 s success copy gatsby files — 0.024 s success onPreBootstrap — 0.006 s success source and transform nodes — 0.104 s success building schema — 0.326 s success createPages — 0.056 s success createPagesStatefully — 0.032 s success onPreExtractQueries — 0.004 s success update schema — 0.185 s success extract queries from components — 0.134 s success run graphql queries — 0.694 s — 9/9 13.00 queries/second success write out page data — 0.012 s success write out redirect data — 0.001 s info bootstrap finished - 5.674 s done generating icons for manifest success onPostBootstrap — 0.287 s success Building production JavaScript and CSS bundles — 11.784 s success Building static HTML for pages — 0.844 s — 7/7 28.27 pages/second Generated public/sw.js, which will precache 11 files, totaling 283621 bytes. info Done building in 18.685 sec Executing pre-flight checks... Compressing application. Beaming package to its final destination. W: Route '{default}' doesn't map to a domain of the project, mangling the route. Provisioning certificates Validating 1 new domain Provisioned new certificate for 1 domains of this environment (Next refresh will be at 2019-04-20 20:19:01+00:00.) Environment certificates - certificate 18bf626: expiring on 2019-05-18 20:19:01+00:00, covering master-7rqtwti-..platformsh.site Creating environment -master-7rqtwti Environment configuration gatsbyjs (type: nodejs:8.9, size: M, disk: 5120) Environment routes http://master-7rqtwti-..platformsh.site/ redirects to https://master-7rqtwti-..platformsh.site/ https://master-7rqtwti-..platformsh.site/ is served by application `gatsbyjs` ```

Let’s review the output of your push. After a basic Git push output, Platform.sh kicks in and runs the build script. Under where it says Executing build hook you can see it downloading npm packages and then running Gatsby.

Building application 'gatsbyjs' (runtime type: nodejs:8.9, tree: fafb3d4)
      Generating runtime configuration.

      Building a NodeJS application, let's make it fly.
      Found a `package.json`, installing dependencies.

        > sharp@0.21.3 install node_modules/sharp
        > (node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)
        ...
        up to date in 14.102s

        success open and validate gatsby-configs — 0.009 s
        success load plugins — 0.325 s
        success onPreInit — 0.895 s
        success delete html and css files from previous builds — 0.096 s
        success initialize cache — 0.016 s
        success copy gatsby files — 0.024 s
        success onPreBootstrap — 0.006 s
        success source and transform nodes — 0.104 s
        success building schema — 0.326 s
        success createPages — 0.056 s
        success createPagesStatefully — 0.032 s
        success onPreExtractQueries — 0.004 s
        success update schema — 0.185 s
        success extract queries from components — 0.134 s

        success run graphql queries — 0.694 s — 9/9 13.00 queries/second
        success write out page data — 0.012 s
        success write out redirect data — 0.001 s



        info bootstrap finished - 5.674 s

        done generating icons for manifest
        success onPostBootstrap — 0.287 s
        success Building production JavaScript and CSS bundles — 11.784 s
        success Building static HTML for pages — 0.844 s — 7/7 28.27 pages/second
        Generated public/sw.js, which will precache 11 files, totaling 283621 bytes.
        info Done building in 18.685 sec

(It’s not as fast as Hugo, but still decently fast.)

Platform.sh then checks that everything seems correct and deploys the container to a host. Again, it generates Let’s Encrypt TLS certificates for every route automatically and ends with the URLs of the application:

      Environment routes
        http://master-7rqtwti-<project ID>.<region>.platformsh.site/ redirects to https://master-7rqtwti-<project ID>.<region>.platformsh.site/
        https://master-7rqtwti-<project ID>.<region>.platformsh.site/ is served by application `gatsbyjs`

The last output is your application’s new URL. You can also check that the project has been successfully deployed on the web interface. If you’ve got the Platform.sh CLI installed, jumping to the web interface from your project is simple; no need to remember project IDs, just type platform web.

Now your basic GatsbyJS site is up and running!

As a side note, we’ve been focused this week on showing how you can run alternate frameworks and a variety of languages on Platform.sh. Did you know that you can run multiple applications inside the same project? This multi-app setup is a subject for another post, however it’s worth noting that combining purpose-built services, like a site built with an SSG, with a blog powered by WordPress, or a headless e-commerce back end powered by Magento or Drupal Commerce, is quite straightforward. Gatsby makes it especially easy, since it’s client-side framework was designed to consume APIs directly.

Tomorrow, we’ll take a look at our final SSG, and the most popular, Jekyll a SSG written in Ruby.

Read the series: Four days, four languages, four frameworks 1. Day 1, Java: Running Brightspot CMS on Platform.sh 2. Day 2, Go: Hugo, a fast static site generator