© Joe Attardi 2020
J. AttardiUsing Gatsby and Netlify CMShttps://doi.org/10.1007/978-1-4842-6297-9_2

2. Gatsby Crash Course

Joe Attardi1 
(1)
Billerica, MA, USA
 

As mentioned in the book’s introduction, familiarity with Gatsby is assumed. But, just in case, this chapter will give a quick overview of the basic concepts in Gatsby.

What is Gatsby?

Gatsby (https://gatsbyjs.org) is a static site generator for React. Pages are created using React components, then are run through a build process which produces static HTML files and associated assets. These assets can then be deployed to a hosting service like Netlify. Despite the name, a site generated by a static site generator can have dynamic content on the client side. Pages can still contain interactive React components or fetch data over HTTP.

The main difference is, while most React applications are single-page applications (SPAs), Gatsby sites typically have multiple HTML files for different pages.

Creating pages

To create a page in a Gatsby site, you simply create a new React component inside the src/pages directory. The file name will determine the URL path to the page. If the file is named index.js, then it will be accessed at the root of the site. Otherwise, the URL path to the page is the file name without the .js extension. For example, the page src/pages/about.js can be accessed at /about.

GraphQL and Gatsby

GraphQL plays an important role in a Gatsby site. It is a powerful query language that allows you to specify which fields you want returned from the query. With a REST API, the full data set is always returned. GraphQL allows you to get only a subset of the data, as shown in Figure 2-1.
../images/502348_1_En_2_Chapter/502348_1_En_2_Fig1_HTML.jpg
Figure 2-1

Querying a data structure with GraphQL

During the build, Gatsby creates a data structure containing all the site’s data. What this data structure contains depends on the plugins being used (more on that later). For example, this data structure may contain data about Markdown files discovered during the build, site metadata, or images. To generate site content, Gatsby pages and their associated React components can query this data using GraphQL.

It is important to note that these GraphQL queries are executed at build time, not at runtime.

To define queries, Gatsby provides a tag called graphql. This tag is used to create tagged templates in the source code: graphql`Your query here`. This utilizes the template strings feature of JavaScript that was added in ES6. Unlike normal template strings, however, you cannot use the ${} interpolation syntax as it is not supported for GraphQL queries. During the build process, Gatsby finds these tagged templates, extracts their text content, and builds GraphQL queries with them.

Listing 2-1 shows an example of a simple query to fetch the title of the Gatsby site.
{
  site {
    siteMetadata {
      title
    }
  }
}
Listing 2-1

A simple Gatsby GraphQL query

The data returned from a GraphQL query has the same structure as the query itself. For example, Listing 2-2 shows the data that would be returned from the query in Listing 2-1.
{
  site: {
    siteMetadata: {
      title: 'My Web Site'
    }
  }
}
Listing 2-2

The result of the GraphQL query

The GraphiQL tool

Gatsby also ships with a tool called GraphiQL. When the site is running in development mode, the tool can be accessed at http://localhost:8000/___graphql. GraphiQL is a visual development environment for browsing the GraphQL schema, composing queries, and viewing the results. Figure 2-2 shows a screenshot of the GraphiQL tool.
../images/502348_1_En_2_Chapter/502348_1_En_2_Fig2_HTML.jpg
Figure 2-2

The GraphiQL tool user interface

On the left is a tree showing the entire schema. Queries can be built interactively by clicking checkboxes next to properties in the schema. In the next panel, the source of the query can be seen, where it can be edited. The third panel shows the result of the query. Lastly, there is also a documentation browser that shows documentation for the different schema elements.

Query types

There are two types of queries in Gatsby.

Page queries

Page queries can only be used in top-level page components. A page query is used by exporting a GraphQL query from the same file as the page component. The result of this GraphQL query is passed to the page as a prop called data.

Listing 2-3 has an example of an index page that queries for the site title.
import React from 'react';
import { graphql } from 'gatsby';
// this is the page
export default function Index({ data }) {
  return (
    <div>
      <h1>Welcome to {data.site.siteMetadata.title}!</h1>
    </div>
  )
}
// this is the page query
export const query = graphql`
  {
    site {
      siteMetadata {
        title
      }
    }
  }
`;
Listing 2-3

A simple page with a page query

Page queries can use variables. Gatsby pages have a concept of a page context, which is a way to pass data to dynamically created pages. The properties in this context object can be filled in as variables in a query. We’ll see an example of this when we cover dynamic page creation below.

Static queries

Static queries can be used in pages as well as components at any level in the component tree. A static query cannot use variables. Static queries can be used either with the StaticQuery component or with the useStaticQuery hook. These are both provided with Gatsby.

The StaticQuery component

Gatsby’s StaticQuery executes a GraphQL query, then renders a component, passing the query result to it. It expects two props:
  • query: The GraphQL query to execute

  • render: A function that takes one argument, the result of the GraphQL query, and returns a React element

Listing 2-4 shows an example component that uses the StaticQuery component.
import React from 'react';
import { graphql, StaticQuery } from 'gatsby';
export default function SiteTitle() {
  return (
    <StaticQuery
      query={graphql`
        {
          site {
            siteMetadata {
              title
            }
          }
        }
      `}
      render={data => (
        <div>{data.site.siteMetadata.title}</div>
      )} />
  )
}
Listing 2-4

Using StaticQuery

The useStaticQuery hook

A newer alternative to the StaticQuery component is the useStaticQuery hook , which can be used inside of a function component. This requires a version of React that supports React Hooks.

To use it, you simply call useStaticQuery from inside your function component. Listing 2-5 shows the same component but using useStaticQuery instead of StaticQuery.
import React from 'react';
import { graphql, useStaticQuery } from 'gatsby';
export default function SiteTitle() {
  const data = useStaticQuery(graphql`
    {
      site {
        siteMetadata {
          title
        }
      }
    }
  `);
  return <div>{data.site.siteMetadata.title}</div>;
}
Listing 2-5

Using the useStaticQuery hook

Plugins

Out of the box, Gatsby doesn’t do much. You can create pages from React components and compose your pages using components, but that’s about it. Gatsby’s real power lies in its plugin ecosystem.

There are many kinds of plugins, but the two we’ll focus on here are source plugins and transformer plugins.

Source plugins

Without any plugins, the Gatsby GraphQL schema doesn’t have much in it. Source plugins add more data from different sources. They gather data from a given source, then call Gatsby’s createNode function to add it to the GraphQL schema.

In our example project, we will use the gatsby-source-filesystem plugin. This plugin adds data about files in the local filesystem. Given a source directory, it will create new GraphQL nodes for each file.

There are many other source plugins, for different APIs, content management systems, and more. They all fetch data from some data source and add that data to the GraphQL schema. There are source plugins for CMS platforms such as Contentful or WordPress, as well as sources for services such as Shopify (for building ecommerce sites) or even for pulling files directly from a Git repository.

Transformer plugins

Transformer plugins take the data from source plugins and transform them into something more useful. For example, suppose you have a directory full of Markdown files you want to use for blog posts. The first step is to use the gatsby-source-filesystem plugin to add the Markdown files to the GraphQL schema.

However, this doesn’t expose the content of the Markdown files. For this, you can use the gatsby-transformer-remark plugin. This plugin reads the Markdown files and exposes the metadata in the front matter (Front matter is a block of metadata at the beginning of a Markdown file). It also uses Remark, a Markdown processing library, to transform the Markdown source into rendered HTML.

Like source plugins, the gatsby-transformer-remark plugin adds new nodes to the GraphQL schema containing the front matter metadata and rendered HTML. For example, all of the Markdown files that were found are accessible in a query via the allMarkdownRemark field . An example query is shown in Listing 2-6.
query BlogQuery {
  allMarkdownRemark {
    edges {
      node {
        html
        frontmatter {
          title
        }
      }
    }
  }
}
Listing 2-6

An example query using gatsby-transformer-remark

You might be wondering what the edges and node fields are in the query. The allMarkdownRemark field is known as a connection. This is a type that represents a group of nodes of a given type. The conceptual model of GraphQL is that of a graph, so you can think of it as a node with edges connecting it to other nodes, as visualized in Figure 2-3.
../images/502348_1_En_2_Chapter/502348_1_En_2_Fig3_HTML.jpg
Figure 2-3

GraphQL edges and nodes

The allMarkdownRemark field has an edge field, which is the set of edges shown in Figure 2-3. Each of the edges has a node field, which is connected to the actual data.

Some other examples of transformer plugins are gatsby-transformer-json, which transforms data from a JSON source, and gatbsy-transformer-yaml, which transforms data from a YAML source. In all, there are over 145 different transformer plugins available in the Gatsby plugin ecosystem.

Other plugins

Besides source and transformer plugins, there are other types of Gatsby plugins as well. These include gatsby-plugin-netlify-cms, which integrates the Netlify CMS user interface with the Gatsby site, and gatsby-plugin-sass, which allows Sass style sheets to be used instead of CSS.

Dynamic page creation

Gatsby pages can be added by creating new files in the pages directory. These pages are defined ahead of time. But for our site to work, we’ll need to configure Gatsby to dynamically create pages.

This is done with a special file, gatsby-node.js. This file provides the ability to implement functions that are called during certain events in the Gatsby build process.

For example, the onCreateNode function is called every time Gatsby creates a node in the GraphQL structure. This could be used, for example, to define additional metadata on some created nodes.

Pages are dynamically created by implementing the createPages function. Gatsby calls this function after the GraphQL schema is created. Because of this, you can execute GraphQL queries to get data that can be used to dynamically create pages.

The createPages function is passed as an object with some helper objects, one of which is actions. That actions object contains, among other things, a helper function called createPage. To create a page, this function is called with the desired URL path, the component to use for the page, and the page context, where we can add custom data.

This context data can then be passed into variables in the page’s GraphQL query. For example, you might query for all blog entries via allMarkdownRemark, then call createPage for each of the returned entries, passing the slug (identifying portion of the page URL) of the Markdown data to the context, as shown in Listing 2-7.
blogEntries.forEach(({ node }) => {
  createPage({
    path: node.fields.slug,
    component: path.resolve('./src/templates/blog.js'),
    context: {
      slug: node.fields.slug
    }
  });
});
Listing 2-7

Dynamically creating a page

The code in Listing 2-7 calls createPage for each blog entry that was found. The React component found in the file ./src/templates/blog.js will be used to render the page, and the slug will be passed to the page’s context, which will then be used in a query variable of the same name, as shown in Listing 2-8.
export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
    }
  }
`;
Listing 2-8

A page query that uses a variable, passed in via the context

Markdown primer

Netlify CMS publishes its content as Markdown files. Gatsby reads and parses those files to render the content using the gatsby-transformer-remark plugin. Because we’re using the CMS, we won’t have to write Markdown directly. But in case you haven’t been exposed to it before, here’s a quick introduction.

Markdown is a lightweight language for formatting text, created in 2004. It uses plain text files with a very simple set of symbols for formatting. Usually, the Markdown is run through a parsing and rendering process to output HTML.

Basic formatting

There are varying “flavors” of Markdown, but here is some of the common formatting syntax:
  • Headings: A heading is preceded by one or more pound sign characters (#). The heading level is determined by the number of pound signs. # is heading 1, ## is heading 2, etc.

  • Paragraphs: Paragraphs are separated by blank lines.

  • Bold: Text is made bold by putting either two asterisks (**) or underscores (__) at the beginning and end of a string. For example, **I'm bold** or __I'm bold__.

  • Italic: Text is made italic by putting either a single asterisk (*) or underscore (_) at the beginning and end of a string. For example, *I'm italic* or _I'm italic_.

  • Unordered lists: One item per line, preceded by either an asterisk or dash. For example:
    - Item One
    - Item Two
  • Ordered lists: One item per line, preceded by a number, starting with 1. For example:

    1. Item One
    2. Item Two
  • Links: Links follow the format [Link text](Link URL).

Front matter

Some tools, such as Gatsby, support the embedding of metadata in a Markdown file This is done in a special section at the beginning of the file called the front matter. This section contains key/value pairs, with the key and value separated by a colon. The front matter begins and ends with three dashes on their own line.

Listing 2-9 shows an example of a Markdown file with front matter.
---
title: "Shopping List"
author: "John Doe"
---
# Shopping List
Here are some items I need to pick up at the grocery store.
- milk
- eggs
- cheese
Listing 2-9

Markdown with front matter

Gatsby starters

You could set up a Gatsby site from scratch if you wanted to. But there are many Gatsby starters that already exist. These are templates for different types of Gatsby sites. They are hosted on GitHub, and a new site can be created by running the command gatsby new <site name> <URL of starter>.

Our example project was created with the most minimal starter, called gatsby-starter-hello-world. There are many other popular starters that you could use to create a Gatsby site, such as
  • gatsby-starter-blog: A basic blog.

  • gatsby-starter-default: A basic starter with a few predefined pages.

  • gatsby-starter-deck: Create presentations powered by Gatsby.

For a full list of starters, visit www.gatsbyjs.org/starters.

The build process

The Gatsby build process goes through several steps to transform your source code into static assets ready to be deployed. Here are the main high-level steps that are performed.

Data model and GraphQL schema creation

First, Gatsby builds its internal data model. This is the data that we can query with GraphQL in our pages and components. What this data model looks like depends on what plugins are configured for the site. This is where source and transformer plugins are executed, adding nodes to the data.

Once the data model is created, the GraphQL schema is built. This is the schema against which queries are validated.

Page creation

Once the data model is created, dynamic page creation takes place, calling the createPages function if it is defined in gatsby-node.js.

Query extraction

Gatsby now searches for GraphQL queries. It does this by creating an abstract syntax tree (AST) of the JavaScript files and looking for templates tagged with graphql. The queries are compiled, and if any of them contain a syntax error, the build process fails.

Query execution

Now the queries are actually executed against the data. First, static queries are executed, followed by page queries. The resulting data is passed to the page and non-page components for the next step.

Static HTML generation

Here is where Gatsby differs from a traditional React application. In a typical React application, the user interface is built completely at runtime in the browser using React. The only HTML that comes from the server is a shell page containing an empty element where the generated markup will be inserted. The UI is not visible until (1) the JavaScript files are downloaded and (2) the JavaScript code is executed to build the UI. This can sometimes have a performance penalty.

Gatsby performs a static render of the React components. This means that as part of the build process, React code runs that generates the HTML markup. This markup is saved to static HTML files. When a visitor loads a page on a Gatsby site, the full HTML of the page is served to the client.

Of course, a static HTML page is not very useful, especially if you want to create an interactive application. This is where the process of hydration comes in.

When a visitor loads the page, since the HTML has already been generated, it appears very quickly. In the meantime, the JavaScript code for the interactive portions of the page are being loaded. Once the JavaScript is available, React takes control of the page. Event listeners are added, and state is injected into the components. After the hydration process completes, the static page has been transformed into a full-blown React application.

Summary

In this chapter, we took a high-level look at Gatsby, its concepts, and its build process:
  • Gatsby is a static site generator for React.

  • Gatsby uses GraphQL for its data model. Pages and components perform GraphQL queries to retrieve their necessary data.

  • Gatsby has a rich plugin ecosystem, including source plugins and transformer plugins.

  • Plugins add data to the site’s GraphQL schema.

  • Markdown is a simple markup language for formatting text, which Gatsby and Netlify CMS use for data.

  • Static HTML is generated at build time; later, hydration is used to transform the page into an interactive React application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.16.23