Gatsby is introduced

What is Gatsby

Gatsby is an open source framework for static sites based on React that helps developers build extremely fast websites. It can be said that it is a static site generator. The main application technologies of Gatsby are React and GraphQL.

Liverpoolfc.tv: Gatsby

Why Gatsby

Gatsby can quickly use the React ecosystem to generate static websites with higher performance, and The Gatsby ecosystem is also powerful.

When you want to build a personal blog by yourself, you should consider SEO, and you do not need to pay attention to the complex deployment Settings such as database and server. The website Gatsby built is a static site, so you can easily deploy the website on many services. Gatsby doesn’t need to wait for requests to generate pages. Instead, it generates pages in advance, so the website is fast.

Gatsby adopted React, React-Router, Webpack, GraphQL and other new technologies, which also followed the technological trend.

GraphQL introduction

We talked about GraphQL, if you’re not familiar with it.

GraphQL is a query language for apis and an alternative to Restful apis.

As for the replacement of Restful apis, I personally feel that Restful apis now occupy an absolutely dominant position, and it is still difficult to be shaken at present. For now, GraphQL has its drawbacks.

Don’t be afraid to see that you haven’t learned GraphQL, because you don’t use it much and Gatsby has a built-in interface for us to operate. GraphQL is very popular in foreign countries. As a new technology, we can have a look at it without going into depth.

Here, of course, we have to extol its advantages, the above definition you may wonder, isn’t the API written back end interface, how can still query?

GraphQL is a graphical Query Language that describes the syntax of how a client requests data from a server. That sounds vague, but what pain points does its relatively Restful API address?

  1. Ask for the data you want no more, no less

I’m sure most of you have encountered a scenario, such as a project management system, where you go to a page and show a list, and the list only shows the title, but you ask for more data, such as who created it, when it was created, etc. This information is redundant here, but it may have its own raison d ‘etre, or other scenarios need to return it, so the interface contains all the data directly.

At this point, GraphQL gets exactly what you want, no more, no less, and returns whatever data you want. The data is controlled by the application, not the server.

  1. Obtaining multiple resources requires only one request

GraphQL queries can not only retrieve the attributes of a resource, but also further query along inter-resource references. While typical REST apis load multiple urls to request multiple resources, GraphQL can get all the data you need for your application in a single request. As a result, applications using GraphQL are fast enough to perform even over slow mobile connections.

  1. Describes all possible type systems

The GraphQL API is organized based on types and fields, not entry endpoints. You can get all your data capabilities from a single entry point. GraphQL uses types to ensure that applications only request possible data, and also provides clear auxiliary error messages. Applications can use types instead of writing manual parsing code.

Gatsby used GraphQL as a way to manage resources locally.

Set up the project

start

  • Installation of Gatsby Scaffolding
npm install -g gatsby-cli
Copy the code
  • New project

Gatsby New [projectName][Starter] : Creates a new project based on the starter

gatsby new gatsby-blog-demo https://github.com/gatsbyjs/gatsby-starter-hello-world
Copy the code

We use the official hello-world template for development, if you use it directly

gatsby new gatsby-blog-demo
Copy the code

By default, the gatsby-starter-default is used to create a new project

  • Run the project
cd gatsby-blog-demo
gatsby develop
Copy the code

Open localhost:8000 and you’ll see Hello world!

Common commands

Here are some of the commands Gatsby used:

  • Gastby Develop: Start the hot loading development environment
  • Gastby Build: Package in public all the static resources, static pages, and JS code needed to build an optimized static site for production
  • Gatsby Serve: After you pack, start a local service where you can test the static web pages just generated by the “Gatsby Build”

GraphiQL

Open http://localhost:8000/__graphql and you’ll see the GraphQL debug interface, where you can view all the data and see if the debug Query statement returns the corresponding data. Query statements can be generated automatically by clicking on the left.


Possible warnings

If your console appears after running:

React-Hot-Loader: react-hot-dom patch is not detected. React 16.6+ features may not work.
Copy the code

It can be solved like this:

npm install @hot-loader/react-dom
Copy the code

Create a new gatsby-node.js file in the root directory

exports.onCreateWebpackConfig = ({ getConfig, stage }) => {
  const config = getConfig()
  if (stage.startsWith('develop') && config.resolve) {
    config.resolve.alias = {
. config.resolve.alias, 'react-dom': '@hot-loader/react-dom'  }  } } Copy the code

Restarting the project eliminates this warning

The project structure

├ ─ ─ the cache├ ─ ─ the public├ ─ ─ the SRC| └ ─ ─ pages / / files under this folder will be mapped to routing| └ ─ ─ index. Js├─ Static // Static Resources├ ─ ─ prettierignore├ ─ ─ prettierrc├─ Gatsby -config.js // Basic Configuration file├ ─ ─ LICENSE├ ─ ─ package. Json├ ─ ─ the README, md└ ─ ─ yarn. The lockCopy the code

Gatsby Configuration file

The initial template here has only one configuration file, whereas a typical project has four

gatsby-config.js

Basic configuration files. The entire Gatsby site configuration file. You can configure the basic information of the website in it.

gatsby-node.js

Node configuration files. This file is only run once during builds, such as dynamically creating some pages.

gatsby-browser.js

Client configuration. Some browser-specific apis are implemented in this file, such as listening for route changes, registering serviceworkers, and so on.

gatsby-ssr.js

The server renders the configuration file. Use Gatsby’s server rendering API to customize the default Settings that affect server rendering.

Create the page

Routing page

We create a file about. Js in the pages directory, and the route path is /about

import React from 'react'

const About = (a)= > {
  return <div>about me</div>
}
 export default About Copy the code

Open the http://localhost:8000/about, shows the page we just created

404 pages

The file name in the Pages directory is the routing path, but there is a special one. When the path cannot be matched, Gatsby will jump to the 404 page. If we create the file name 404.js under pages, our self-defined 404 page will be used. Current we just input a nonexistent page path: http://localhost:8000/test, would be an error page.

Let’s create a new file called 404.js

import React from 'react'

const About = (a)= > {
  return <div>404 page does not exist</div>
}
 export default About Copy the code

Enter another path to display the page:

Gatsby makes sure the 404 page is built as 404.html, which is created for us by default. It also lists all the page routing links on the site. We can see the 404 page we just created by clicking on the Preview Custom 404 Page.

So we want to go directly to our custom 404 page, which requires us to click to jump to. The reason is that in the development environment, when Using Gatsby Develop, Gatsby overwrites our custom 404 pages with the default 404 page, which is actually already in effect.

We can package, start a local service, simulate an online environment, and then directly display our custom 404 page.

gatsby build
gatsby serve
Copy the code

Then open the http://localhost:9000/test (arbitrary path), will be able to jump to a custom 404 page for us


Creating layout components

  1. Create a new directory SRC/Components.

  2. Create a layout component file SRC/Components /layout.js in the directory above:

import React from 'react'

export default ({ children }) => (
  <div style={{ margin: `3rem auto`, maxWidth: 650.padding: `0 1rem` }}>{children}</div>
)
Copy the code
  1. insrc/pages/index.jsAdd the Layout component to the
import React from 'react'
import Layout from '.. /components/layout'

export default function Home() {
  return <Layout>Hello world!</Layout>
} Copy the code

This keeps the entire screen centered, and the basic actions of React are here

Setting CSS Styles

Styles in Gatsby can take many forms, but we won’t mention the common import ‘./xxx. CSS.

Use global styles

One of the most straightforward ways to add global styles to a website is to use global.css stylesheets.

Create folder styles under SRC and add a global.css file

html {
  background-color: #f5f5f5;
}
Copy the code
  • In the create Gatsby -browser.js directory, import the style file
import "./src/styles/global.css"
Copy the code

Restart the local service and notice that the background of the page has changed to light gray.

Use CSS Modules to style components

CSS Modules reduce global contamination and prevent naming conflicts and style overwriting.

The CSS Module is implemented by changing the names of all modular classes to unique names, that is, adding some unique prefixes or suffixes. This prevents overwriting and conflicting styles written by different people in a project.

  1. Creating a CSS Filesrc/styles/index.module.css
.title {
  color: red;
}
.text {
  color: blue;
} Copy the code

Usage: SRC /pages/index.js

import React from "react"
import Layout from ".. /components/layout"
import styles from ".. /styles/index.module.css"

export default function Home() {
 console.log(styles)  return (  <Layout>  <h1 className={styles.title}>Hello World</h1>  <div className={styles.text}>Test</div>  </Layout>  ) } Copy the code

Running results:


Print styles to see the result of the imported processing:

If you compare this to a CSS file, you’ll see that each format is now a key that points to a long string in the import object, for exampletitlePoint to theindex-module--title--1i-Wh. These style names are generated by the CSS module. Make sure they are unique on your site. And because you have to import them to use these classes, it’s fine to use these CSS styles anywhere.

Other ways of dealing with CSS

CSS styles are enough, others like Sass, etc. There are also STYLES of CSS in JS, such as Emotion, Styled Component. You can go to the official website to check the supported Gatsby plug-in, then you can use it.

Get the data in Gatsby

When building a website, you may need to reuse some common data – such as common site titles, author information, etc. We can’t add it on every page, so we store the title in one location and reference that location from other files, and only change it in one place.

The location of this common data is the siteMetadata object in the Gatsby -config.js file. Open this file and write the code:

module.exports = {
  /* Your site config here */
  siteMetadata: {
    title: `Title from siteMetadata`,
    author: 'jacky'
 },  plugins: [], } Copy the code

Restart the service

Using page query

Edit the SRC/pages/about. Js

import React from 'react'
import { graphql } from 'gatsby'

// The data obtained by GraphQL is passed to the page component as parameters
// Data is of the form {errors, data}, without errors there would be no errors
const About = ({ data }) = > {  console.log(data.site.siteMetadata.title)  return (  <div>  <h1>Title: {data.site.siteMetadata.title}</h1>  <p>author: {data.site.siteMetadata.author}</p>  <div>about me</div>  </div>  ) }  export default About  export const query = graphql`  query {  site {  siteMetadata {  title  author  }  }  } ` Copy the code

And then you pull out the data


Where the GraphQL query statement is:

{
  site {
    siteMetadata {
      title,
      author
 }  } } Copy the code

This is the GraphQL query statement. You can open the built-in GraphQL debugging interface of Gatsby http://localhost:8000/__graphql.

The site here is the configuration of the site written by our gatsby-config.js.

Click site and siteMetadata on the left successively, and then there are title and author fields we wrote just now for us to choose. At the same time, the middle box will generate query statement, and finally click the run button to output the query result.


When you need to get more complex nested data later, you can directly find and click in this interface, automatically generate query statements on the line.

You can get as much data as you want. For example, I want to get the title and not the author

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
 }  }  } ` Copy the code

Queries using non-page components (static queries)

Note here that we need to distinguish between the two query methods. The query method in the above example is only applicable to page query, that is, routing interface under SRC/Pages. If GraphQL query is performed under non-page components, the above method cannot be used. The StaticQuery component or useStaticQuery hook should be used.

// page queryexport const query = graphql`
    query{ ... }
`
Copy the code

For example, we create a component SRC/Components /header.js

  • StaticQuery
import React from 'react'
import { graphql, StaticQuery } from 'gatsby'

const Header = (a)= > (
  <StaticQuery  query={graphql`  query {  site {  siteMetadata {  author  }  }  }  `}  render={data= > {  const {  site: { siteMetadata },  } = data  return <div>This is the Header component and the author is: {siteMetadata. Author}</div>  }}  /> )  export default Header Copy the code

Or use the useStaticQuery method

  • useStaticQuery
import React from "react"
import { useStaticQuery, graphql } from "gatsby"

const Header = () => {
  const data = useStaticQuery(
 graphql`  query {  site {  siteMetadata {  author  }  }  }  `  )  returnThe < div > this is the Header component, the author is: {data. Site. SiteMetadata. Author} < / div >}  export default Header Copy the code

Then import the Header component in SRC /pages/index.js

import React from 'react'
import Layout from '.. /components/layout'
import Header from '.. /components/header'
import styles from '.. /styles/index.module.css'

export default function Home() {  return (  <Layout>  <Header />  <h1 className={styles.title}>Hello World</h1>  <div className={styles.text}>Test</div>  </Layout>  ) } Copy the code

The running results are as follows:


The plug-in

gatsby-source-filesystem

This is the Data source plug-in of Gatsby, which converts all aspects of data into content that can be extracted locally through GraphQL for setting the file system of the project.

  • Installing a plug-in
npm install --save gatsby-source-filesystem
Copy the code
  • Configure in the gatsby-config.js file
module.exports = {
  siteMetadata: {
    title: `Title from siteMetadata`.    author: 'jacky'.  },
 plugins: [  {  resolve: `gatsby-source-filesystem`. options: {  name: `src`.// The name can be used to filter  path: `${__dirname}/src/`.// File path  },  }, ].} Copy the code

Restart the service

Go to http://localhost:8000/__graphql and look at allFile and File options.

Let’s click on the optional “allFile” and select the ones shown below


Note that the data you are querying is basically under edges. Node. Node is a special name for an object in the graph, and each File node contains the field you are querying.

The ID,name, and relativePath fields we selected correspond to the files we created in our SRC directory, and there are many other fields to choose from, giving you a variety of information about the seven files we created.

If you can query it here, it means you can query it in the component and then use the data, so you can query it in the component and make a list of files.

Compared to the traditional React project, the React project can easily capture the data without doing any complicated work. Gatsby more powerful is its ecological, many plug-ins are match well, more can see the website of the plugin library is introduced: https://www.gatsbyjs.org/plugins/

gatsby-transformer-remark

This is the data conversion plugin, which is essential if we use Gatsby as our personal blog. We programmers use Markdown syntax to write blogs now, and parsing markdown syntax is a must for a blog.

  • Installing a plug-in
npm install --save gatsby-transformer-remark
Copy the code
  • Configure in the gatsby-config.js file
module.exports = {
  /* Your site config here */
  siteMetadata: {
    title: `Title from siteMetadata`.    author: 'jacky'. },  plugins: [  {  resolve: `gatsby-source-filesystem`. options: {  name: `src`.// The name can be used to filter  path: `${__dirname}/src/`.// File path  },  },  `gatsby-transformer-remark`.].} Copy the code

Restart the service

The plug-in adds two data fields, allMarkdownRemark and markdownRemark


  • Creating an MD File

Create the _posts directory under SRC and add a first-blog.md file

---
title: "My first blog."
date: "2020-06-21"
tags: "React"
categories: "The React series"
---  ## This is the title of the first blog post  Content of First Blog 1Copy the code

If the blog is not built by yourself, but directly on a platform to write, you may not understand the above syntax, at the beginning of the MD file – wrapped in frontMatter (preface), and then can add a variety of keywords in the article information.

We can then query the details of the MD file we wrote at http://localhost:8000/__graphql


Let’s change it a little bit and create two more MD files

second-blog.md

---
title: "My second blog post."
date: "2020-06-22"
tags: "Vue"
categories: "Vue series"
---  ## This is the title of the second blog post  Second Blog content 2Copy the code

third-blog.md

---
title: "My third blog post."
date: "2020-06-23"
tags: "React"
categories: "The React series"
---  ## This is the title of the third blog post  Third Blog content 3Copy the code

Query the data again and remove all the article data we just added


Since GraphQL can get the data, we can display it on a page.

Create a new file SRC /pages/blog.js and make a summary of the blog directory:

import React from 'react'
import Layout from '.. /components/layout'
import { graphql } from 'gatsby'

const Blog = ({ data }) = > {
 return (  <Layout>  <h1>Blog directory</h1>  <div>  {data.allMarkdownRemark.edges.map(({ node }) => {  return (  <div  key={node.id}  style={{  border: '1px solid #000',  margin: '10px',  padding: '10px',  }}  >  <h2>{node.frontmatter.title}</h2>  <div>Classification of {node. The frontmatter. Categories}</div>  <div>Tags: {node. The frontmatter. Tags}</div>  <div>{node.frontmatter. Date}</div>  </div>  )  })}  </div>  </Layout>  ) }  export default Blog  export const query = graphql`  query {  allMarkdownRemark {  edges {  node {  id  frontmatter {  tags  title  date  categories  }  }  }  }  } ` Copy the code

Open the http://localhost:8000/blog, a blog directory is displayed:


The problem is, we can actually get the information for each blog post, but we have to link, which means click on the blog title, go to the blog details page, which is the post path, so we’re going to create the page.

Create pages using data

gatsby-node.js

This is the time to create the Gatsby -node.js file. The code in this configuration file is node layer specific.

Previously we said that all files in the SRC/Pages directory are rendered as routes, but it would not make sense if the detail pages of our blog posts required us to create our own JS file.

We will use two apis:

onCreateNode

Gatsby calls the onCreateNode function every time a new node (or update) is created.

Write the code to gatsby-node.js:

exports.onCreateNode = ({ node }) = > {
  console.log(node.internal.type)
}
Copy the code

Restart the service, look at the terminal, and you’ll see a number of created nodes printed: SitePage, SitePlugin, Site, SiteBuildMetadata, Directory, File, MarkdownRemark, all we care about is MarkdownRemark, Modify the function so that it only records MarkdownRemark nodes; We use the name of each MD File as the path. To get the File name, you need to walk through its parent File, which contains the File data we need.

exports.onCreateNode = ({ node, getNode }) = > {
  if (node.internal.type === `MarkdownRemark`) {
    const fileNode = getNode(node.parent)
    console.log(`\n`, fileNode.relativePath)
  }
} Copy the code

Restart the service and view the terminal. The following output is displayed:

 _posts/first-blog.md

 _posts/second-blog.md

 _posts/third-blog.md
Copy the code

To create a path, use the function attached with the Gatsby – source-Filesystem to create a path

const { createFilePath } = require(`gatsby-source-filesystem`)

exports.onCreateNode = ({ node, getNode }) = > {
  if (node.internal.type === `MarkdownRemark`) {
    console.log(createFilePath({ node, getNode, basePath: `pages` }))
 } } Copy the code

Restart the service. The following information is displayed:

/_posts/first-blog/
/_posts/second-blog/
/_posts/third-blog/
Copy the code

Next, we pass a function to the API, createNodeField, which allows us to create additional fields in nodes created by other plug-ins.

exports.onCreateNode = ({ node, getNode, actions }) = > {
  const { createNodeField } = actions
  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })
    createNodeField({
 node,  name: `slug`. value: slug, // The word slug is usually used to represent a path  })  } } Copy the code

Restart the service, open http://localhost:8000/__graphql, you can query the path


createPages

CreatePages this API is used to add pages. Before you create a page, you need to have a page template so that you can specify which template to use when creating the page.

Create a new file SRC /templates/blog-post.js

import React from 'react'
import Layout from '.. /components/layout'

export default() = > {  return (
 <Layout>  <div>Hello blog post</div>  </Layout>  ) } Copy the code

Then change the Gatsby – Node. js createPages function:

const path = require(`path`)

exports.createPages = async ({ graphql, actions }) => {
  const result = await graphql(`
 query {  allMarkdownRemark {  edges {  node {  fields {  slug  }  }  }  }  }  `)  result.data.allMarkdownRemark.edges.forEach(({ node }) = > {  createPage({  path: node.fields.slug,  component: path.resolve(`./src/templates/blog-post.js`),  context: {  slug: node.fields.slug,  },  })  }) } Copy the code

Restart the service, enter a path to the default 404 page, and you’ll see the path to three automatically generated blogs. If you click on any of these, you’ll see the path to the blog-post.js component we just created.


We want to display blog content, so we need to modify the template file again:

import React from 'react'
import { graphql } from 'gatsby'
import Layout from '.. /components/layout'

export default ({ data }) => {
 const post = data.markdownRemark  return (  <Layout>  <div>  <h1>{post.frontmatter.title}</h1>  <div dangerouslySetInnerHTML={{ __html: post.html}} / >  </div>  </Layout>  ) }  export const query = graphql`  query($slug: String!) {  markdownRemark(fields: { slug: { eq: $slug } }) {  html  frontmatter {  title  }  }  } ` Copy the code

The above is a dynamic variable query method and GraphQL syntax, can look at (https://graphql.org/learn/queries/#variables)

When I’m done, say I click on the second blog post, I’ll be right on the page and displaying the content


To make things better, we added reachable links to the blog directory page, added slug query fields, and added Link redirect. This usage is almost the same as Link in the React route.

src/pages/blog.js

import React from 'react'
import Layout from '.. /components/layout'
import { graphql, Link } from 'gatsby'

const Blog = ({ data }) = > {
 return (  <Layout>  <h1>Blog directory</h1>  <div>  {data.allMarkdownRemark.edges.map(({ node }) => {  return (  <Link to={node.fields.slug} key={node.id}>  <div  style={{  border: '1px solid #000',  margin: '10px',  padding: '10px',  }}  >  <h2>{node.frontmatter.title}</h2>  <div>Classification of {node. The frontmatter. Categories}</div>  <div>Tags: {node. The frontmatter. Tags}</div>  <div>{node.frontmatter. Date}</div>  </div>  </Link>  )  })}  </div>  </Layout>  ) }  export default Blog  export const query = graphql`  query {  allMarkdownRemark {  edges {  node {  id  frontmatter {  tags  title  date  categories  }  fields {  slug  }  }  }  }  } ` Copy the code

Now click on the blog, you can jump to the corresponding page, although the style page is not ugly, but just create a new MD file in the SRC /_posts directory, and then it will automatically refresh, which is a super easy blog.

Package online

Stop developing the service, build the production version, and export the static files to the public directory

gatsby build
Copy the code

To view the production environment version locally, run:

gatsby serve
Copy the code

Next, you can access the site we just made at localhost:9000

Github address of this project

That’s it for the tutorial.


  • Ps: Personal technical blog Github warehouse, if you feel good welcome star, give me a little encouragement to continue writing ~