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
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.
A simple Gatsby GraphQL query
The result of the GraphQL query
The GraphiQL tool
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.
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
query: The GraphQL query to execute
render: A function that takes one argument, the result of the GraphQL query, and returns a React element
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.
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.
An example query using gatsby-transformer-remark
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.
Dynamically creating a page
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
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 One2. Item TwoLinks: 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.
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>.
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
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.