Gatsby 教程:从零开始构建 Gatsby 网站的分步指南

2025-06-07

Gatsby 教程:从零开始构建 Gatsby 网站的分步指南

在这个时代,现代网站正在快速采用单页应用程序(SPA)设计方法,即用户的交互无需重新加载页面即可立即反映在用户界面中。

发生这种情况是因为文件是提前生成的,从而无需使用网络服务器。

这是一种构建性能更佳的网站的新方法。

在本文中,您将学习如何使用 Gatsby 从头开始​​构建此类网站并免费在网络上部署。

在继续之前,你需要了解 React。所以,先学习完本React 教程,然后再回来。

对于那些熟悉编写 React 代码的人来说,让我们开始吧。

盖茨比是什么?

Gatsby 或 GasbyJS是一个基于 React 库和 GraphQL 的框架,可以轻松创建网站和 Web 应用程序。它基于 JAMstack 构建,即一种基于客户端 JavaScript(或其他脚本)、可重用 API 和预构建标记构建网站/应用程序的策略。

该类型的站点具有高性能、可扩展性和安全性。

不过,根据 Gatsby 与其他 Jamstack 技术(Jekyll、Next、Hugo 等)的共同之处,Gatsby 被视为静态站点生成器(SSG)。

但实际上,它能做的事情比静态站点生成器通常能做的多得多。

您可以将 Gatsby 视为用于构建复杂网站和 Web 应用程序的 React 框架。

有了 Gatsby,你不再局限于静态网站。你可以使用 React、GraphQL、无头 CMS 等最新工具,构建博客网站、电商网站或任何复杂的网站。

Gatsby 之所以如此受欢迎,是因为它运行速度快,使用方便。它让我们能够管理来自不同来源的内容。

如果您是技术人员,您可以从 Markdown 文件中管理和获取您的内容。

或者,您可以从 Contentful、WordPress 或 Drupal 等 CMS 获取内容。这样,您可以构建一个由 Gatsby 驱动的静态网站,同时仍然可以通过一个美观的管理界面管理您的内容。

无论哪种方式,都有 Gatsby 插件可以让我们实现其中任何一个。

在本教程中,你将学习如何通过 Markdown 文件获取和管理你的内容。在后续教程中,你将学习如何从 Contentful CMS 获取内容。

这就是我们将在本教程中构建的Gatsby 站点项目。您可以在我的GitHub 仓库中找到所有代码

说得够多了,让我们开始吧。

初始设置

要开始使用 Gatsby,您需要在您的机器上安装 NodeJS 和 Git。

使用 NodeJS,你可以在 Web 浏览器之外运行 Gatsby JavaScript 代码。你还可以访问其 npm(Node 包管理器)工具。

您可以通过在终端中运行npm -v和来检查它是否已安装。node –v

命令应该返回各自的版本。

如果没有,请前往NodeJS 网站,下载并安装最新版本。

同样,您需要 Git 来安装 Gatsby 启动文件。

Git 是一个免费的开源分布式版本控制系统,旨在快速高效地处理小型或大型项目。

如果您尚未安装,请前往Git 网站,下载并安装适合您的操作系统的版本。

安装 Git 的步骤因操作系统而异。因此,如果您需要帮助,请查看本指南

完成后,您需要安装 Gatsby CLI(命令行界面)。

此 CLI 将允许您生成一个新的 Gatsby 项目。它可以作为 npm 包使用。

因此,请转到您的终端并运行此 npm 命令:

npm install -g gatsby-cli

注意:-g标志表示您正在机器上全局安装 CLI。

生成你的第一个 Gatsby 项目

Gatsby 允许我们使用任意一个入门模板来启动项目。Gatsby 团队官方发布了许多内置模板。此外,还有数百个由第三方开发者创建的模板。

使用这些模板,您可以创建各种有趣的网站和应用程序。

由于本 Gatsby 教程的目标是探索基本功能,因此我们将使用具有最基本功能的 Gatsby 启动器 - 即没有插件和样板。

这将帮助你理解基础知识。一旦你理解了,你就能使用任何入门工具了。

因此,我们将安装官方的hello world启动器。

通过 CLI 安装新的 Gatsby 启动器的惯例是:

gatsby new [PROJECT_DIRECTORY] [STARTER_URL]

好的,从终端切换到您想要保存项目的目录(例如cd Desktop)并运行:

gatsby new ibaslogic-gatsby-tutorial https://github.com/gatsbyjs/gatsby-starter-hello-world

这将创建一个名为ibaslogic-gatsby-tutorial的新项目文件夹(您可以随意命名)并包含所有启动文件。

新的 Gatsby 网站成功启动后,请使用您最喜欢的代码编辑器打开它。就我而言,我将使用 VsCode。

您的项目结构应如下所示:

项目结构

在我们查看项目文件夹之前,让我们先运行开发服务器。

为此,我们将运行 Gatsby 提供的脚本之一。

package.json如果您在根目录中打开文件并检查scripts属性,您将看到如下内容:

"scripts": {
  "build": "gatsby build", 
  "develop": "gatsby develop",
  "format": "prettier --write \"**/*.{js,jsx,json,md}\"",
  "start": "npm run develop",
  "serve": "gatsby serve",
  "clean": "gatsby clean",
  "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},

你应该把重点放在develop脚本上。这将允许你启动开发服务器并在本地构建项目。此脚本还支持实时刷新,以便实时反映更改。

稍后我们将探讨一些其他脚本属性。

您可以从计算机终端或 VsCode 的集成终端(如果您正在使用它)启动您的 Gatsby 站点。

从计算机终端导航到您的站点目录:

cd ibaslogic-gatsby-tutorial

然后运行:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > gatsby develop

如果您使用的是 VsCode,则可以从(或分别在 Windows 和 Mac 上View -> Terminal使用快捷方式Ctrl + `或)打开其集成终端并运行cmd + `gatsby develop

命令完成后,您将看到一条成功消息,其中包含查看默认启动站点的链接。

Gatsby 开发

继续在浏览器中打开该网站http://localhost:8000

记下第二个 URL,http://localhost:8000/___graphql。稍后我们开始将数据拉取到网站时再探讨这一点。

Gatsby 第一个网站

如果您看到此信息,则表示您已成功创建并启动了您的第一个 Gatsby 网站。

恭喜。

注意:如果您使用 Git bash,则可能会在终端中收到一些警告。例如:有多个模块的名称仅大小写不同……

修复方法很简单

确保在终端中,文件路径中的目录名称在所有情况下都一致。例如,路径中应该包含Desktop ,但不应该包含Desktop

目前,该网站还没有什么特别有趣的内容。我们稍后会定制我们所看到的内容。

首先,你需要了解项目结构。让我们来看看项目目录中的一些重要文件和文件夹。

项目目录内

由于使用过 React,我希望你对项目(文件夹和文件)的结构有所了解。为了便于理解,我将快速介绍一些重要的文件夹和文件。

node_modules文件夹包含所有第三方库以及 Gatsby 本身。此目录还将包含本教程后面将通过 npm 安装的软件包。

public文件夹将包含您网站的公共资产并保存您的静态文件。

src文件夹将包含您的所有工作文件。您将大部分时间都花在这里。在这个文件夹中,我们有一个pages目录。这是 Gatsby 项目中非常重要的一个目录。此文件夹中的任何文件都会自动转换为静态页面,并根据其文件名生成路径。目前,它index.js位于 pages 文件夹中。如您所知,索引文件始终指向主页。这就是为什么该文件的内容会在前端渲染的原因。

不用担心src文件,我们将从头开始编写所有内容。

static文件夹是包含您的重定向文件、网站图标甚至徽标的好地方。

顾名思义,该gatsby-config.js文件是您配置 Gatsby 网站的地方。在此文件中,您可以设置网站标题、描述、要包含的 Gatsby 插件以及其他一些配置。稍后您将学习如何完成所有这些操作。

最后,package.json包含有关您网站的信息。它包含一些当前已安装库的依赖项,如果您安装了其他软件包,它们也会列出。

现在您已经熟悉了项目结构,让我们继续对前端进行简单的更改。

我之前提到过,该src/pages文件夹包含网站静态页面的文件。因此,请进入文件夹并打开该index.js文件。该文件中的代码是一个简单的 React 组件,用于在屏幕上渲染一个简单的“Hello world!”。如果您将“hello world!”文本更改为其他内容并保存文件,则更改将实时反映在浏览器中。

发生这种情况是因为 Gatsby 与热重载捆绑在一起。

很好的开始!

使用 Gatsby Pages

正如预期的那样,焦点将集中在src/pages目录上。目前,我们只有index.js此文件夹中的文件。

在创建页面时,Gatsby 会查找此目录来确定你的网站需要哪些静态页面。因此,你放入此目录的所有文件都将代表你的网站页面。

那么让我们开始处理该index.js文件。

同时,将代码替换为以下内容:

import React from "react"

const Index = () => {
  return (
    <div>
      <h1>Home page</h1>
      <h2>I'm Ibas, a teacher and a Gatsby.js developer</h2>
    </div>
  )
}

export default Index

保存文件并在前端查看更改。

这就是创建 Gatsby 页面所需的全部内容。

我们所做的只是渲染一个简单的 React 功能组件。

如果您对代码理解有困难,请继续阅读本React 教程然后再回来。

那么当 Gatsby 生成我们的网站时究竟发生了什么?

它首先会检查src/pages文件夹,以确定应该创建哪些静态页面。在我们的例子中,它发现我们只有一个文件,也就是index.js。这意味着我们的网站只有一个页面。

现在文件的名称也很重要。这里,文件名为index.js。这类似于index.html网站主页的默认页面。

使用 Gatsby 时,index.js它将是默认主页。
要创建新页面,只需向src/pages目录添加一个新文件即可。在本教程中,我们将创建另外三个页面:博客联系信息关于页面。

因此,让我们在文件夹中创建这些文件blog.js-contact.jsabout.jssrc/pages

在该blog.js文件中,添加以下代码:

import React from "react"

const Blog = () => {
  return (
    <div>
      <h1>Blog Page</h1>
      <p>Blog posts will be displayed here!</p>
    </div>
  )
}

export default Blog

保存文件并在浏览器地址栏中输入http://localhost:8000/blog/即可查看该页面。其中,URL 中的“blog”是页面文件的名称。

以同样的方式,进入contact.js文件并添加以下代码:

import React from "react"

const Contact = () => {
  return (
    <div>
      <h1>Contact Page</h1>
      <p>You can find Ibas on Twitter via @ibaslogic</p>
    </div>
  )
}

export default Contact

对于about.js文件,添加以下内容:

import React from "react"

const About = () => {
  return (
    <div>
      <h1>About Page</h1>
      <p>Ibas is a web developer, teacher and a creative writer.</p>
    </div>
  )
}

export default About

保存您的文件,不要忘记访问http://localhost:8000/contact/http://localhost:8000/about/ 的页面。

创建 Gatsby 页面布局组件

现在,我们不再通过在浏览器地址栏中导航到相应的 URL 来访问所有页面,而是创建另一个名为 的组件Header

该组件将呈现包括导航菜单链接在内的标题内容。

这样,用户就可以轻松访问每个页面。

一种方法是将Header组件导入到每个页面的文件中。

但这样做有一个缺点。

想象一下,如果网站变得复杂,添加了新的页面,你就需要通过添加Header组件来不断更新每个新页面。与其这样做,不如创建一个通用Layout组件,它可以容纳所有共享组件。在我们的例子中,Header当然是…… Footer

然后我们可以标记每个页面以包含该Layout组件。

让我们看看它是如何工作的。

Header组件开始。

在目录中src,创建一个名为 的新文件夹components。在此文件夹中,添加一个名为 的文件header.js,并添加以下代码:

import React from "react"

const Header = () => {
  return (
    <div>
      This is the header content
    </div>
  )
}

export default Header

与此同时,我们正在呈现一个简单的文本。

该文件尚未执行任何操作。我们需要将其导入到某个地方。

不在页面文件中,而是在布局文件中。所以让我们创建这个文件。

进入components文件夹并创建layout.js文件。然后添加以下代码:

import React from "react"
import Header from "./header"

const Layout = (props) => {
  return (
    <div>
      <Header />
      {props.children}
    </div>
  )
}

export default Layout

保存文件。

接下来,将这个新Layout组件导入到所有页面的组件文件中。

例如,该index.js文件现在看起来像这样:

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

const Index = () => {
  return (
    <Layout>
      <h1>Home page</h1>
      <h2>I'm Ibas, a teacher and a Gatsby.js developer</h2>
    </Layout>
  )
}

export default Index

请注意我们如何用标签包装内容<Layout></Layout>

保存所有文件并检查前端索引/主页。

索引页

对其他页面执行相同操作。

您所要做的就是将Layout组件导入页面并用Layout标签包装内容。

我们做了什么?

我们构建组件的方式Layout使得管理网站页面变得简单。在layout.js文件中,我们接收children来自页面的 props。

注意:在 React 中,我们可以通过 prop 访问组件内部的内容children

props.children组件中用到了什么Layout

<Layout></Layout>嗯,它是在不同页面的标签之间传递的 JSX 。

这是纯粹的 React,没什么特别的。

Gatsby 网站中的页面之间的链接

创建了网站的标题部分后,让我们更新Header组件以呈现网站标题和导航菜单。

import React from "react"
import { Link } from "gatsby"

const Header = () => {
  return (
    <header>
      <div>
        <p>
          <Link to="/">Ibas Majid</Link>
        </p>
        <p>I teach JavaScript, React, GraphQL and Gatsby</p>
      </div>
      <nav>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/blog/">Blog</Link>
          </li>
          <li>
            <Link to="/contact/">Contact</Link>
          </li>
          <li>
            <Link to="/about/">About</Link>
          </li>
        </ul>
      </nav>
    </header>
  )
}

export default Header

保存文件并在前端查看更改。

在代码中,我们利用模块<Link />中的组件gatsby来链接内部页面。与常规 HTML 标签相比,这进行了大量优化<a>

例如,点击 HTML 锚点元素会导致页面刷新。但Link标签可以让页面立即加载,从而提供更好的用户体验。

这里,我们使用to属性来引用目标页面,而不是使用标签href中的属性<a>

要使用该Link组件,你必须从gatsby模块中导入它,并使用它来链接你的 Gatsby 站点内的页面。使用常规<a>标签可以链接到任何外部页面。

挑战!

创建共享页脚并将其渲染到每个页面上。您可以重新访问页眉部分来完成此操作。

完毕?

我们一起做吧!

components文件夹中创建一个footer.js文件并添加以下代码:

import React from "react"

const Footer = () => {
  return (
    <footer>
      <p>
        Site developed by Ibaslogic &copy; {new Date().getFullYear().toString()}{" "}
      </p>
    </footer>
  )
}

export default Footer

然后更新layout.js文件,以便您拥有:

...

import Footer from "./footer"

const Layout = props => {
  return (
    <div>
      <Header />
      {props.children}
      <Footer />
    </div>
  )
}

...

保存您的文件并检查前端。

现在您的网站应该如下所示:

布局渲染

在文件中footer.js,我们动态调用当前年份。记住,我们可以通过花括号在 React JSX 中使用有效的 JavaScript {}

盖茨比网站造型

现在,我们网站上的内容已经相当丰富,各个页面也都分布着,我们需要通过添加样式来改善外观和体验。目前看起来很糟糕。

在本节中,您将学习如何使用 CSS 轻松地设置您的 Gatsby 网站的样式。

在此过程中,您还将学习如何设置 Gatsby 插件以启用 SASS。您将能够充分利用其所有强大功能,并进一步自定义您的网站。

如果您对 SASS 不熟悉,请随意使用常规 CSS 样式。

那么让我们开始吧。

进入src目录并创建一个名为 的新文件夹styles。在此文件夹中,创建一个名为 的文件style.css并添加以下基本样式:

* {
  box-sizing: border-box;
}
body {
  color: #464646;
  font-size: 100%;
  margin: 0;
  line-height: 1.4283;
  font-family: "Segoe UI", Roboto, Verdana, "Helvetica Neue", sans-serif;
}
h1,
h2,
h3 {
  font-weight: 400;
}
a {
  color: #f44f18;
  text-decoration: none;
}

之后,Layout像这样在组件中导入 CSS 文件:

import "../styles/style.css"

使用该组件的原因Layout是它在每个页面的文件中都有使用。

保存您的文件并查看在前端应用的样式。

这是一个很好的起点。

现在,你的 Gatsby 网站已经加载了样式表。你可以直接在这个文件中编写所有样式。

但在本教程中,我们不会这样做。

正如我提到的,我们将使用 sass 来加速网站定制。这也是学习如何在 Gatsby 项目中集成 sass 并安装你的第一个 Gatsby 插件的好时机。

那么我们就这么做吧。

安装和配置 gatsby-plugin-sass

您可能已经知道,网站插件可以为网站添加功能。

Gatsby 提供了大量由其团队构建的插件以及由其社区成员开发的第三方插件。

您可以访问Gatsby 网站并导航到插件页面来搜索这些插件。

现在,我们将要安装的 sass 插件名为gatsby-plugin-sass

CTRL + C因此,让我们根据CMD + C您的操作系统停止开发服务器。

从您的终端运行:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > npm install gatsby-plugin-sass node-sass

node-sass允许我们将.scss文件编译为常规文件css。同时gatsby-plugin-sass允许我们在 Gatsby 项目中执行此操作。

安装完成后,你需要配置你的 Gatsby 网站以使用 Gatsby 插件。
因此,打开gatsby-config.js文件并将文件中的所有内容替换为以下内容:

module.exports = {
  plugins: ["gatsby-plugin-sass"],
}

保存文件并通过运行启动开发服务器gatsby develop

接下来,将style.css文件重命名为style.scss并更新文件import中的layout.js以反映.scss扩展名,如下所示:

import "../styles/style.scss"

保存您的文件。

您仍然应该在前端应用您的样式。

现在您可以在项目中使用 sass 了。

让我们在scss文件中应用 sass 变量。因此,请将文件更新为如下所示:

$primaryColor: #464646;
$secondaryColor: #f44f18;
$mainWhite: #fff;

* {
  box-sizing: border-box;
}
body {
  color: $primaryColor;
  font-size: 100%;
  margin: 0;
  line-height: 1.4283;
  font-family: "Segoe UI", Roboto, Verdana, "Helvetica Neue", sans-serif;
}
h1,
h2,
h3 {
  font-weight: 400;
}
a {
  color: $secondaryColor;
  text-decoration: none;
}

保存文件。耶,成功了!

使用 CSS 模块来设计 Gatsby 网站

为了在我们的 Gatsby 网站中添加某种全局样式,我们在共享Layout组件中添加了一个样式表。

虽然此样式表文件可以容纳您所有的站点样式,但建议将此文件限制为全局样式,并使用 CSS 模块在本地限定您的组件样式范围。

Gatsby 项目默认支持 CSS 模块,它们消除了与 CSS 选择器发生名称冲突的风险或与全局范围样式相关的其他一些问题。

例如,如果你为Header组件添加了 CSS 模块,则应用的样式将仅限于该组件。这样,你可以在不同的组件中使用相同的类名,而不必担心与 CSS 选择器冲突。

这就是我们想要的。

Header组件开始。

让我们进入src/components目录并创建一个名为的文件header.module.scss。然后,添加以下样式:

.header {
  position: relative;
  height: 326px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}

.hero-content {
  position: absolute;
  top: 35%;
  margin: 0;
  text-align: center;
  width: 100%;
  text-transform: uppercase;
}

.brand {
  margin: 0;
  padding: 0 0 10px;
  font-size: 48px;
  font-weight: 300;
  line-height: 1.2;
  letter-spacing: 5.5px;

  a {
    color: #fff;
  }
}

.description {
  margin: 0;
  padding: 0 0 10px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 3.5px;
  opacity: 0.7;
  color: #fff;
}

.nav-container {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.1);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.nav-list {
  margin: 0;
  display: flex;
  flex-flow: wrap;
  justify-content: center;
  padding: 0;
  list-style: none;

  li {
    letter-spacing: 0.05em;
    background: none;
    padding: 7px 14px 10px;
  }

  a {
    text-transform: uppercase;
    color: #fff;
    font-size: 12px;
    opacity: 0.7;

    &:hover {
      text-decoration: underline;
    }
  }
}

.module.css请注意,如果您在文件中写入内容,则会将 添加到文件名中.css。另请注意,我们将 css 选择器和伪类 ( :hover) 缩进文件中的另一个选择器内.scss。这在文件中不起作用css

之后,进入header.js文件并导入.scss文件,如下所示:

import headerStyles from "./header.module.scss"

然后,更新语句中的标记return以包含类名:

return (
  <header className={headerStyles.header}>
    <div className={headerStyles.heroContent}>
      <p className={headerStyles.brand}>
        <Link to="/">Ibas Majid</Link>
      </p>
      <p className={headerStyles.description}>
        I teach JavaScript, React, GraphQL and Gatsby
      </p>
    </div>
    <nav className={headerStyles.navContainer}>
      <ul className={headerStyles.navList}>    
        ...
      </ul>
    </nav>
  </header>
)

保存您的文件并检查前端。

我们需要在标题部分添加背景图像。

因此,进入src目录并创建一个名为的文件夹images。在此文件夹中,添加背景图像并将其命名为header-image.jpg

您可以随意使用硬盘上的任何图片。或者,您可以访问我的 GitHub 仓库,下载本项目中使用的相同标题图片。

然后更新文件.header中的类选择器,header.module.scss以便:

.header {
  position: relative;
  height: 326px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  background-image: url("../images/header-image.jpg");
}

在保存文件之前,让我们为背景图像添加一个覆盖层。

在文件中,在开始标记后立即header.js添加以下内容div<header>

<div className={headerStyles.overlay}></div>

然后更新header.module.scss文件以包含以下样式:

.overlay {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: #000;
  opacity: 0.5;
}

现在保存所有文件。你的前端应该如下所示:

CSS模块

那么我们做了什么?

首先,我们通过将 SCSS 文件附加到文件 来告诉 Gatsby 将 SCSS 文件作为 CSS 模块进行处理.module.scss。然后,将该模块导入到header.js文件中,并将其声明为名为 的 JavaScript 对象headerStyles

该对象保存了文件中的所有类选择器.scss,我们在 JSX className 属性中引用它们headerStyles.classSelector(例如headerStyles.header)。

请注意,

您可以随意命名headerStyles对象。此外,任何带有连字符 ( – ) 的选择器都可以在.js文件中使用其驼峰命名法 (camelCase) 版本引用。例如,当我们在文件内的属性中引用它时,文件.hero-content中的.scss会转换为heroContentclassName.js

如果您在浏览器开发者工具中检查标题元素,您会发现 CSS 模块会生成唯一的类名,如下图所示。这样,您就不必担心选择器名称冲突了。

css 模块类

在继续设置其他组件的样式之前,我们先来设置活动导航菜单项的样式。这将告诉网站用户当前正在浏览哪个页面。

为此,请进入header.js文件并更新<Link />组件以包含该activeClassName属性。

<ul className={headerStyles.navList}>
  <li>
    <Link to="/" activeClassName={headerStyles.activeMenuItem}>Home</Link>
  </li>
  <li>
    <Link to="/blog/" activeClassName={headerStyles.activeMenuItem}>Blog</Link>
  </li>
  <li>
    <Link to="/contact/" activeClassName={headerStyles.activeMenuItem}>Contact</Link>
  </li>
  <li>
    <Link to="/about/" activeClassName={headerStyles.activeMenuItem}>About</Link>
  </li>
</ul>

当当前项目处于活动状态时,activeClassName属性将被应用。Link

现在进入header.module.scss文件并添加此样式:

.active-menu-item {
  text-decoration: underline;
}

保存您的文件并查看前端应用的样式。

现在您已经了解了 CSS 模块的工作原理,让我们继续为正文和页脚部分添加一些样式。

我们希望页脚始终位于页面底部。因此,我们将设置一个粘性页脚。

这很简单!

更新layout.js文件,使其看起来像这样:

...

import "../styles/style.scss"
import layoutStyles from "./layout.module.scss"

const Layout = props => {
  return (
    <div className={layoutStyles.container}>
      <div className={layoutStyles.content}>
        <Header />
        <div className={layoutStyles.mainContent}>{props.children}</div>
      </div>
      <Footer />
    </div>
  )
}

...

return 语句中的标记是粘性页脚的常见结构。其中,页眉和主要内容放置在div容器中,而页脚放置在容器外部。

您会注意到我们导入了一个名为的 css 模块文件layout.module.scss。因此您需要创建该文件。

在同一src/components目录中,创建一个layout.module.scss文件并添加以下内容:

.container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.content {
  flex-grow: 1;
}

.main-content {
  margin: 0 auto;
  max-width: 750px;
  padding: 3rem 1rem 4rem;
}

保存文件。

以同样的方式,更新footer.js文件,以便获得:

import React from "react"
import footerStyles from "./footer.module.scss"

const Footer = () => {
  return (
    <footer className={footerStyles.siteFooter}>
      <div className={footerStyles.container}>
        <p>
          Site developed by Ibaslogic &copy;{" "}
          {new Date().getFullYear().toString()}{" "}
        </p>
      </div>
    </footer>
  )
}

export default Footer

然后在目录中创建footer.module.scss文件components并添加以下内容:

.site-footer {
  background-color: #000;
  color: #515151;
}
.container {
  margin: 0 auto;
  max-width: 750px;
  padding: 1rem;
}

保存文件并检查前端。你的页面应该如下所示:

css 模块主体

现在您已经有了一些样式,让我们继续并开始将动态数据导入我们的网站。

使用 Gatsby 数据

到目前为止,我们正在 React 组件 JSX 中编写浏览器中显示的所有内容。

随着网站变得越来越复杂,这种方法将无法扩展。相反,您需要将数据存储在组件外部,并动态地将其加载到网站中。

在本节中,您将学习如何使用GraphQL API将数据导入您的 Gatsby 网站

如果你从未使用过 GraphQL,也没关系。我们会在使用过程中讲解其基础知识。

GraphQL 只是一种用于向客户端加载数据的查询语言。它允许客户端精确指定所需的数据。

您马上就会看到它是如何工作的。

与其他站点生成器不同,Gatsby 不仅允许我们从 Markdown 等文件系统获取数据,还允许我们从 API、数据库、CMS(如 Contentful、WordPress、Drupal 等)获取数据。

这就是让盖茨比变得非常有趣和强大的原因。

让我们从基础开始。

在您的 Gatsby 网站中,您可能希望重复使用并轻松更改一些数据,例如网站标题、描述、网站作者、社交句柄等。这些数据可以存储在一个位置(您可以在其中轻松更改它们)并从其他文件中引用它们。

这个位置就是文件siteMetadata中的对象gatsby-config.js

进入gatsby-config.js文件并添加另一个siteMetadatamodule.export对象同名的属性,如下所示:

module.exports = {
  siteMetadata: {
    title: "Ibas Majid",
    description: "I teach JavaScript, React, GraphQL and Gatsby",
    author: "Ibaslogic"
  },
  plugins: ["gatsby-plugin-sass"],
}

保存文件。

现在,您需要查询这些数据并在您的网站中使用它们。

为此,你需要知道如何使用一个名为GraphiQL的工具。该工具是一个用于探索 GraphQL API 的浏览器内 IDE(集成开发环境)。

您可以通过http://localhost:8000/___graphql访问此工具。

注意:URL 中有 3 个下划线,并且仅当您网站的开发服务器正在运行时才可用。

打开该工具后,单击顶部的资源管理器按钮即可查看资源管理器面板。

GraphiQL IDE

在您开始使用 GraphiQL 时,此面板将帮助您快速上手。您将能够通过点击可用字段来构建查询,而无需手动输入查询语句。

但是如果您更喜欢手动输入这些查询,则可以使用Ctrl + SpaceShift + Space调出自动完成窗口。

从网站元数据获取内容

我们将首先获取之前指定的数据siteMetadata。这些数据可以在Explorer面板的站点下拉字段中找到

但他们还不会出现。

这是因为无论何时更改gatsby-config.js文件,您都必须重新启动开发服务器并刷新 GraphiQL。

因此重新启动 gatsby 开发并再次检查站点下拉字段。

如下图所示,该siteMetadata字段包含您提供的数据(在gatsby-config.js文件中)可供选择。

选择您想要的字段,然后单击播放按钮来运行查询。

站点元数据

查询结果以JSON格式显示在右侧。

在 GraphQL 中,你可以执行三种主要类型的操作——查询修改订阅。但使用 Gatsby,我们只关注查询操作类型。

GraphiQL 中的查询MyQuery 操作名称)是可选的。一旦您确定页面上没有其他查询,就可以决定从查询中省略它们。

现在我们已经获得了想要的数据,我们将查询移到我们的 Gatsby 站点并加载这些数据。

查询类型

Gatsby 允许我们通过页面查询StaticQuery将数据加载到组件中。现在,要使用的查询类型取决于组件类型。无论是页面组件还是非页面组件。

页面组件位于src/pages目录中,并自动成为站点页面。此类型可以使用任一查询类型。

另一方面,非页面组件嵌入在其他组件或多个页面组件中。例如,HeaderFooterLayout组件。此类组件只能使用StaticQuery类型或其 React hooks 版本useStaticQuery

在我们的网站中,我们希望获取组件中的网站标题和描述Header以及组件中的作者Footer

为此,我们将使用StaticQueryuseStaticQuery。我更喜欢后者。

因此,让我们继续对我们的header.js文件进行一些更改并使用useStaticQuery钩子。

更新此import声明:

import { Link } from "gatsby"

到:

import { Link, useStaticQuery, graphql } from "gatsby"

然后,在语句上方添加以下内容return

const data = useStaticQuery(
  graphql`
    query {
      site {
        siteMetadata {
          title
          description
        }
      }
    }
  `
)

return最后,在声明中分别使用{data.site.siteMetadata.title}和引用站点标题和描述{data.site.siteMetadata.description}

您的文件应如下所示:

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

import headerStyles from "./header.module.scss"

const Header = () => {
  const data = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            description
          }
        }
      }
    `
  )
  return (
    <header className={headerStyles.header}>
      <div className={headerStyles.overlay}></div>
      <div className={headerStyles.heroContent}>
        <p className={headerStyles.brand}>
          <Link to="/">{data.site.siteMetadata.title}</Link>
        </p>
        <p className={headerStyles.description}>
          {data.site.siteMetadata.description}
        </p>
      </div>
      <nav className={headerStyles.navContainer}>
        ...
      </nav>
    </header>
  )
}

export default Header

保存文件。

现在,如果您在文件中编辑网站标题和描述gatsby-config.js,您的更改应该会立即显示在前端。

在代码中,我们导入了这个钩子useStaticQuery,它接受 GraphQL 查询并返回数据。然后将数据注入到 JSX 中。

你会注意到我们只查询我们需要的数据——例如标题和描述。这也是 GraphQL 如此强大的原因之一。

继续。

挑战!

更新Footer组件以动态加载作者姓名。

完毕?

我们一起做吧!

footer.js文件中,useStaticQuery从模块导入 graphql,gatsby如下所示:

import { useStaticQuery, graphql } from "gatsby"

之后,在return语句上方添加以下内容:

const data = useStaticQuery(
  graphql`
    query {
      site {
        siteMetadata {
          author
        }
      }
    }
  `
)

jsx然后,在使用中引用作者姓名{data.site.siteMetadata.author},如下所示:

<footer className={footerStyles.siteFooter}>
  <div className={footerStyles.container}>
    <p>
      Site developed by {data.site.siteMetadata.author} &copy;{" "}
      {new Date().getFullYear().toString()}{" "}
    </p>
  </div>
</footer>

保存文件。

好的。

通过修改文件中的作者姓名来测试您的工作gatsby-config.js,并查看前端反映的更改。

从文件系统获取内容

现在您已经了解了如何从中获取内容siteMetadata,让我们更进一步,获取将显示在博客页面上的内容。

我之前提到过,我们可以从本地文件、CMS 或任何其他来源获取博客文章内容。但在本教程中,我们将从本地文件获取博客文章内容。

为了实现这一点,我们将使用两个插件。

首先,一个名为 的源插件gatsby-source-filesystem将获取原始内容并允许我们查询文件的数据。第二个插件gatsby-transformer-remark将允许我们查询文件内部的数据,并将内容(即 Markdown 内容)转换为我们想要的格式(即 HTML)。

让我们看看如何实现这一点。

我们将首先为博客文章创建 Markdown 文件。进入src目录并创建一个名为 的文件夹posts。在此文件夹中,创建两个名为first-gatsby-blog-post.md和 的Markdown 文件second-gatsby-blog-post.md

在该first-gatsby-blog-post.md文件中,添加以下内容:

---
title: "First Gatsby Blog Post"
date: "2020-01-18"
---

Lorem ipsum dolor sit amet consectetur adipisicing elit.

## Excepturi maxime

reprehenderit accusamus, explicabo eligendi necessitatibus soluta! Ipsam mollitia alias temporibus dicta

1. omnis earum nobis
2. architecto, quia
3. officiis aperiam
4. voluptate quaerat

另外,将此内容添加到second-gatsby-blog-post.md文件中:

---
title: "Second Gatsby Blog Post"
date: "2020-01-19"
---
Seprehenderit accusamus, explicabo eligendi necessitatibus soluta! 

## Ipsam mollitia

alias temporibus dictorem ipsum dolor sit amet consectetur adipisicing elit. 

## Excepturi maxime 

omnis earum nobis architecto, quia officiis aperiam voluptate quaerat.

保存您的文件。

frontmatter如(虚线框内)所示,我们指定了帖子的titledate。您可以在此处注入任何数据,例如标签、类别、精选图片 URL、帖子描述等。

现在,我们需要告诉 Gatsby 使用从本地文件中获取内容gatsby-source-filesystem

在您的终端中,停止开发服务器并通过运行以下命令在项目根目录下安装插件:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > npm install gatsby-source-filesystem

然后将其添加到您的gatsby-config.js,使其看起来像这样:

module.exports = {
  siteMetadata: { ... },
  plugins: [
    "gatsby-plugin-sass",
    {
      resolve: "gatsby-source-filesystem",
      options: {
        name: "src",
        path: `${__dirname}/src/`,
      },
    },
  ],
}

通过此配置,我们告诉 Gatsby 从文件系统获取内容。这包括src目录中的所有内容,包括images文件夹。

注意:为了在字符串中嵌入表达式,我们使用模板文字(` `)。

__dirname是 NodeJS 的一个方法,用于返回当前运行文件的绝对路径。目录名前有两个下划线。

保存文件并重新启动开发服务器。

现在让我们转到 GraphiQL IDE 看看添加了什么。

src您可以在资源管理器面板的下拉菜单中找到有关文件的所有详细信息allFile -> edges -> node

记住,源插件允许我们查询文件的数据。下图展示了如何查询文件名、目录和扩展名。

本地文件

您还可以使用自动完成快捷方式在查询区域添加更多字段Ctrl + Space

现在我们正在获取本地文件,让我们继续安装gatsby-transformer-remark将可用的 Markdown 文件(.md)转换为 HTML 的插件。

返回到您的终端,停止开发服务器并运行此安装:

npm install gatsby-transformer-remark

然后将其添加到gatsby-config.js文件中。插件数组现在应如下所示:

plugins: [
  "gatsby-plugin-sass",
  "gatsby-transformer-remark",
  {
    resolve: "gatsby-source-filesystem",
    options: {
      name: "src",
      path: `${__dirname}/src/`,
    },
  },
],

保存文件。启动开发服务器并刷新 GraphiQL IDE。

您会注意到资源管理器面板中新增了allMarkdownRemarkmarkdownRemark。我们将使用allMarkdownRemark来获取博客页面的帖子列表,然后使用markdownRemark来获取单个帖子。

如果您探索节点上可用的某些字段allMarkdownRemark,您将得到如下内容:

所有Markdown备注

在查询区域,您会注意到我们正在传递sort参数,allMarkdownRemark以按照前置内容的日期字段的降序排列博客文章。

请记住,我们在 Markdown 文件的前面date部分指定了。title

如资源管理器面板所示,您还可以向查询传递多个参数(过滤、限制和跳过)。例如,您可以通过指定 来减少查询的总结果数limit。此外,您还可以通过 省略多个结果skip

现在我们有了所需的数据,让我们将它们呈现在我们网站的博客页面上。

因此进入src/pages/blog.js文件并更新它,使其看起来像这样:

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

import Layout from "../components/layout"

const Blog = () => {
  const data = useStaticQuery(
    graphql`
      query {
        allMarkdownRemark(sort: { fields: frontmatter___date, order: DESC }) {
          edges {
            node {
              frontmatter {
                title
                date(formatString: "DD MMMM, YYYY")
              }
              timeToRead
              excerpt
              id
            }
          }
        }
      }
    `
  )
  return (
    <Layout>
      <ul>
        {data.allMarkdownRemark.edges.map(edge => {
          return (
            <li key={edge.node.id}>
              <h2>{edge.node.frontmatter.title}</h2>
              <div>
                <span>
                  Posted on {edge.node.frontmatter.date} <span> / </span>{" "}
                  {edge.node.timeToRead} min read
                </span>
              </div>
              <p>{edge.node.excerpt}</p>
            </li>
          )
        })}
      </ul>
    </Layout>
  )
}

export default Blog

保存文件并检查前端。

您应该在博客页面上显示您的帖子。

博客页面

那么我们做了什么?

如果您查看 GraphiQL 中返回的数据,您会发现 Gatsby 将其内容构造为边缘数组内的对象集合。

edges我们用该方法循环遍历数组,获取每个对象(代表单个帖子数据)map()。这样,我们就可以在 JSX 标记中获取所需的数据。

如果您对 React 有基本的了解,那么您应该熟悉所有这些。

现在我们在博客页面上有了帖子列表,让我们继续创建一个单个帖子页面。

创建单个帖子页面

目前,我们只在博客页面上渲染了 Markdown 内容的摘录。稍后,我们将在最终项目中显示精选图片。

但在此之前,让我们看看如何生成单个帖子页面。

src/pages想象一下,您正在为每个单独的博客文章在目录中创建一个 React 组件。

请记住,此目录中的每个组件都会自动成为一个页面。

这不是你想冒险的事情。

相反,您将学习如何使用 Gatsby 节点 API 动态生成单个帖子页面。

我们可以通过三个简单的步骤实现这一目标:

  1. 生成页面 slug
  2. 创建博客文章页面模板
  3. 为每个帖子生成一个新页面。

第一步仅适用于从 Markdown 文件获取内容的情况。对于像 Contentful 这样的 CMS,您无需自行创建 slug。

为页面生成 slug

在这里,我们将使用一个名为 的 Gatsby 节点 API onCreateNode。此 API 会在新节点创建时调用,允许我们将新数据附加到该节点。在本例中,我们将附加生成的帖子 slug。

让我们看看如何生成 slug 并实现这个 API。

我们将首先gatsby-node.js在根目录中创建一个名为的文件。

在该文件中添加以下内容:

exports.onCreateNode = ({ node }) => {
  if (node.internal.type === "MarkdownRemark") {
    console.log(JSON.stringify(node, null, 4))
  }
}

保存文件并重新启动开发服务器后,您将看到MarkdownRemark节点类型已记录到终端。

大多数情况下,您会希望使用每个 markdown 文件名来生成页面 slug。

您可以通过定位下图所示的内容来完成此操作fileAbsolutePath,然后提取文件名并用作页面 slug。

文件绝对路径

为此,请更新您的gatsby-node.js文件,以便:

const path = require("path")

exports.onCreateNode = ({ node }) => {
  if (node.internal.type === "MarkdownRemark") {
    const slug = path.basename(node.fileAbsolutePath, ".md")
    console.log(slug)
  }
}

在这里,我们使用 NodeJSpath.basename()方法从中提取文件名fileAbsolutePath

再次重新启动开发服务器后,您应该拥有每个 markdown 文件的 slug。

渲染块

现在我们正在生成 slug,我们将把它们添加到MarkdownRemark节点上,以便可以使用 GraphQL 进行查询。

更新gatsby-node.js文件,以便获得:

const path = require("path")

exports.onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === "MarkdownRemark") {
    const slug = path.basename(node.fileAbsolutePath, ".md")
    createNodeField({
      node,
      name: "slug",
      value: slug,
    })
  }
}

createNodeField是一个来自actions对象的函数onCreateNode。它使我们能够在节点上创建附加字段。

保存文件并重新启动开发服务器后,您现在就可以访问字段值(即 slug)node.fields.slug

在 GraphiQL 中,您应该生成类似这样的内容。

创建节点字段

现在已经生成了 slug,让我们继续第二步,即创建博客文章模板。

在这个模板中,您只需创建一个 React 组件。该组件将用于渲染所有博客文章。

src目录中,创建一个名为 的新文件夹templates。在此文件夹中,创建一个名为 的文件blog-post.js并添加以下内容:

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

const BlogPost = () => {
  return (
    <Layout>
      <div>This is the single post template</div>
    </Layout>
  )
}

export default BlogPost

与此同时,我们正在模板文件中渲染一段简单的文本。稍后我们会更新该文件。

现在,让我们为每个帖子生成一个新页面。

为此,我们将使用另一个 Gatsby 节点 API,createPages它允许我们动态添加页面。

在文件底部添加以下代码gatsby-node.js

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

在代码中,我们利用createPagesAPI 函数根据 markdown 动态创建单个帖子页面slug

在这里,我们使用async/await语法从函数中获取承诺响应graphql。此响应包含我们需要的所有数据。

因此,我们循环遍历其edges数组(包含帖子列表),然后通过调用createPage函数动态创建每个帖子页面。

此函数接受一个对象,在该对象中我们定义了path用于访问单个博客文章的,该component参数指定了模板文件的绝对路径,而包含我们传递给模板文件的context数据(即)。slug

现在让我们重新启动开发服务器。

至此,你的博客文章页面已创建完成。你可以在浏览器地址栏中访问http://localhost:8000/blog/first-gatsby-blog-post并查看新页面。

模板

此页面的内容来自模板文件blog-post.js。这绝对不是我们想要的。相反,我们将显示来自 Markdown 帖子文件的数据。

在博客模板中渲染帖子数据

为了完成此操作,我们将设置一个 GraphQL 查询,它将动态接受帖子 slug 并返回博客帖子数据。

为了了解如何做到这一点,让我们使用 GraphiQL IDE。

因此请刷新或重新打开该工具。

这里我们将使用markdownRemark查询来获取单篇文章。在这个查询中,我们将通过参数根据文章的 slug 来定位每篇文章fields

为此,我们将使用查询变量(一组可以传递给查询的数据)。在本例中,我们将传入动态 slug。

您的查询应该看起来像这样。

查询变量

如上所示,GraphiQL 为我们提供了一种在查询中传递变量的方法。但是在模板文件中,变量将来自context您的 对象gatsby-node.js

记住我们在对象中指定了 slug。

注意:变量以 为前缀$,因此slug属性成为$slug查询中的参数。

现在让我们采用这个查询并用它来展示每个单独的帖子。

因此更新src/templates/blog-post.js文件以便您拥有:

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

import Layout from "../components/layout"

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      frontmatter {
        title
        date(formatString: "DD MMMM, YYYY")
      }
      timeToRead
      html
    }
  }
`

const BlogPost = props => {
  return (
    <Layout>
      <div>
        <h1>{props.data.markdownRemark.frontmatter.title}</h1>
        <span>
          Posted on {props.data.markdownRemark.frontmatter.date}{" "}
          <span> / </span> {props.data.markdownRemark.timeToRead} min read
        </span>
        <div
          dangerouslySetInnerHTML={{ __html: props.data.markdownRemark.html }}
        ></div>
      </div>
    </Layout>
  )
}

export default BlogPost

保存文件并重新访问http://localhost:8000/blog/first-gatsby-blog-post

您应该已经渲染了您的帖子。

单篇帖子

好一个!

在代码中,你会注意到我们没有useStaticQuery像以前一样使用查询钩子。这是因为静态查询不能接受查询变量。

相反,我们使用页面查询。

正如您在模板文件中看到的,这种类型的查询存在于组件定义之外。

现在,查询结果通过 props 注入到 React 组件中。从那里,我们可以访问数据并在 JSX 标记中使用它们。

注意:在 JSX 中,我们使用dangerouslySetInnerHTMLprop 来为我们的博客文章呈现 HTML。

现在,我们已经为每篇博客文章准备好了模板。接下来,让我们从博客页面链接到这些新页面。

为了实现这一点,我们需要的是动态 slug。

之前我提到过,slug 可以在 访问node.fields.slug。因此,您可以修改博客页面查询,使其能够访问 ,slugs并使用它们生成链接。

更新您的src/pages/blog.js文件,以便您拥有:

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

import Layout from "../components/layout"

const Blog = () => {
  const data = useStaticQuery(
    graphql`
      query {
        allMarkdownRemark(sort: { fields: frontmatter___date, order: DESC }) {
          edges {
            node {
              frontmatter {
                ...
              }
              ...
              id
              fields {
                slug
              }
            }
          }
        }
      }
    `
  )
  return (
    <Layout>
      <ul>
        {data.allMarkdownRemark.edges.map(edge => {
          return (
            <li key={edge.node.id}>
              <h2>
                <Link to={`/blog/${edge.node.fields.slug}/`}>
                  {edge.node.frontmatter.title}
                </Link>
              </h2>
              <div>
                <span>
                  Posted on {edge.node.frontmatter.date} <span> / </span>{" "}
                  {edge.node.timeToRead} min read
                </span>
              </div>
              <p>{edge.node.excerpt}</p>
              <div>
                <Link to={`/blog/${edge.node.fields.slug}/`}>Read More</Link>
              </div>
            </li>
          )
        })}
      </ul>
    </Layout>
  )
}

export default Blog

请注意代码中的几点。我们在摘录后添加了“阅读更多”链接。另外,请确保从模块中导入组件Linkgatsby

现在您有一个可以运行的博客。

下一步是什么?

在 Gatsby 网站中设置图像

如果您曾经管理过网站博客,您会同意我的观点,加快网站速度的主要方法是在上传之前优化图像。

我们使用不同的编辑工具来修饰、裁剪和调整图像大小,或者如果您使用 WordPress,只需使用插件即可。

这些过程一直都是一个巨大的痛苦。

使用 Gatsby,处理图像变得非常简单,你无需依赖第三方服务来执行图像优化。Gatsby 内置了这项功能。

那么让我们看看它是如何工作的。

在 Gatsby 博客文章中,您可以通过多种方式添加图片。除了在 Markdown 正文中添加图片外,您还可以添加显示在文章顶部的特色图片。

在这里,您将学习如何做到这两点。

将图像添加到 Markdown 主体

首先,我们将使用默认的 Markdown 语法在文章中添加一张图片。因此,请更新你的 Gatsby 文章,使其包含此语法,并检查前端。

![gatsby tutorial](../images/gatsby-tutorial.png)

注意:确保添加文件夹gatsby-tutorial.png中命名的图像src/images

markdown 图片

在前端,您将看到alt显示的图像文本(gatsby 教程)而不是实际图像。

默认情况下,Gatsby 不知道从哪里获取图像。

为了支持这一点,我们将安装一些插件。因此,请前往终端并停止开发服务器。

然后运行:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > npm install gatsby-remark-images gatsby-plugin-sharp

gatsby-remark-images允许我们在 markdown 帖子中使用图像并添加某种优化(响应性、不同宽度的多个版本等),同时gatsby-plugin-sharp负责减小图像的大小。

接下来,进入gatsby-config.js文件并添加这些插件。

module.exports = {
  siteMetadata: { ... },
  plugins: [
    "gatsby-plugin-sass",
    {
      resolve: "gatsby-source-filesystem",
      options: {
        ...
      },
    },
    "gatsby-plugin-sharp",
    {
      resolve: "gatsby-transformer-remark",
      options: {
        plugins: [
          {
            resolve: "gatsby-remark-images",
            options: {
              maxWidth: 750,
              linkImagesToOriginal: false,
            },
          },
        ],
      },
    },
  ],
}

保存文件并运行开发服务器。你应该会看到图片出现在单篇文章页面中。

注意:我们通过选项中gatsby-config.js添加来更新文件gatsby-remark-imagespluginsgatsby-transformer-remark

此图片是您添加的图片的优化版本。它响应式、压缩,并具有延迟加载效果。

接下来,

添加特色图片

特色图片通常放置在frontmatterMarkdown 文件的部分内。

featured因此,向您的帖子添加一个名为的字段,frontmatter如下所示:

---
title: "First Gatsby Blog Post"
date: "2020-01-18"
featured: "../images/first-post.png"
---

注意:确保添加文件夹first-post.png中命名的图像src/images

要查询此特色图片以供使用,您需要安装以下插件。

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > npm install gatsby-image gatsby-transformer-sharp

gatsby-image一个 React 组件,允许我们通过 渲染优化图像(包括固定宽度图像和全宽图像)<Img />。 同时gatsby-transformer-sharp会暴露节点 ,childImageSharp用于处理您的图像。

插件安装完成后,将gatsby-transformer-sharp插件添加到您的gatsby-config.js文件中。

盖茨比变换锋利

保存文件并启动开发服务器。

接下来,我们看看如何从 GraphiQL IDE 查询此图像。

在资源管理器面板中,您会注意到一个名为 的新节点childImageSharp已添加到featuredfrontmatter。在这里,您可以指定所需的图像优化类型(固定或流动)。

盖茨比 图片

请注意,我们同时渲染固定类型和流体类型,以向您展示两者的工作原理。

对于拉伸至容器整个宽度的图像,可以使用 Fluid 属性。对于固定宽度和高度的图像,可以使用 Fixed 属性。

现在我们有了数据,让我们在模板文件中使用查询并将返回的数据传递到提供的Img组件中gatsby-image

src/templates/blog-post.js文件中,更新查询,以便获得:

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      frontmatter {
        title
        date(formatString: "DD MMMM, YYYY")
        featured {
          childImageSharp {
            fluid(maxWidth: 750) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
      timeToRead
      html
    }
  }
`

仍然在模板中,像这样Imggatsby-image模块导入组件:

import Img from "gatsby-image"

fluid然后,您将通过 prop 传递查询中对象返回的数据fluid

因此,在 JSX 中的 span 元素下方添加以下内容。

{props.data.markdownRemark.frontmatter.featured && (
  <Img
    fluid={props.data.markdownRemark.frontmatter.featured.childImageSharp.fluid}
    alt={props.data.markdownRemark.frontmatter.title}
  />
)}

此代码检查您的帖子前言中是否有特色图片。

在这里,我们使用 JavaScript 真值和假值。

它是这样运作的

如果之前的操作数&&为真,即存在特色图片,<Img />则返回第二个操作数(组件)。否则,忽略它。

保存文件。您应该会在单篇文章页面中看到渲染后的特色图片。

在查询中,您会注意到我们src用替换了GatsbyImageSharpFluid。这是一个用于返回图像参数(例如 等)的查询src片段srcSet

注意: GraphiQL IDE 尚不支持查询片段。

在帖子列表页面(博客页面)中为帖子添加缩略图

这应该很容易。你只需要重复上述方法即可。

src/pages/blog.js文件中,更新查询前置字段,以便获得:

frontmatter {
  title
  date(formatString: "DD MMMM, YYYY")
  featured {
    childImageSharp {
      fluid(maxWidth: 750) {
        ...GatsbyImageSharpFluid
      }
    }
  }
}

之后,像这样Imggatsby-image模块导入组件:

import Img from "gatsby-image"

然后在 JSX 中的摘录上方添加以下内容。

{edge.node.frontmatter.featured && (
  <Img
    fluid={edge.node.frontmatter.featured.childImageSharp.fluid}
    alt={edge.node.frontmatter.title}
  />
)}

保存文件并检查博客页面。您应该会看到显示的缩略图。

在我们继续为 Gatsby 网站添加更多样式之前,让我们先更新另一篇 Markdown 文章,添加一张精选图片。

您所要做的就是添加一个指向您图像的featured字段。frontmatter

---
title: "Second Gatsby Blog Post"
date: "2020-01-19"
featured: "../images/second-post.png"
---

就这样。

保存文件并查看前端呈现的图像。

现在,我们的 Gatsby 网站上有一个功能齐全的博客。

让我们继续添加漂亮的外观和感觉。在这里,我们将继续之前开始的 CSS 模块。

如果您感到困惑,请重新回顾之前的解释。

从博客列表页面开始。

进入src/pages目录并创建一个名为 的新文件blog.module.scss。然后,添加以下样式:

.posts {
  list-style-type: none;
  margin: 0;
  padding: 0;
}
.post {
  padding-bottom: 40px;
  &:last-child {
    padding-bottom: 0;
  }
  h2 {
    font-size: 27px;
    margin: 0 0 10px;
    text-align: center;
    a {
      color: #555;
      &:hover {
        color: #222;
      }
    }
  }
}
.meta {
  font-size: 13px;
  text-align: center;
  font-weight: 300;
  margin-bottom: 20px;
}
.featured {
 max-height: 330px;
}
.excerpt {
  margin: 30px 0 15px;
  font-weight: 300;
  letter-spacing: 0.02em;
}
.button {
  font-size: 14px;
  font-weight: 300;
  text-align: center;
  padding: 20px 0;
  a {
    color: #555;
    padding: 8px 12px;
    border: 1px solid #555;
    &:hover {
      color: #fff;
      border-color: #222;
      background-color: #222;
    }
  }
}

之后,进入src/pages/blog.js文件并导入.scss文件,如下所示:

import blogStyles from "./blog.module.scss"

然后,更新语句中的标记return以包含类名。

return (
  <Layout>
    <ul className={blogStyles.posts}>
      {data.allMarkdownRemark.edges.map(edge => {
        return (
          <li className={blogStyles.post} key={edge.node.id}>
            <h2>
              <Link to={`/blog/${edge.node.fields.slug}/`}>
                {edge.node.frontmatter.title}
              </Link>
            </h2>
            <div className={blogStyles.meta}>
              <span>
                Posted on {edge.node.frontmatter.date} <span> / </span>{" "}
                {edge.node.timeToRead} min read
              </span>
            </div>
            {edge.node.frontmatter.featured && (
              <Img
                className={blogStyles.featured}
                fluid={edge.node.frontmatter.featured.childImageSharp.fluid}
                alt={edge.node.frontmatter.title}
              />
            )}
            <p className={blogStyles.excerpt}>{edge.node.excerpt}</p>
            <div className={blogStyles.button}>
              <Link to={`/blog/${edge.node.fields.slug}/`}>Read More</Link>
            </div>
          </li>
        )
      })}
    </ul>
  </Layout>
)

保存您的文件并检查博客页面。

博客页面样式

美丽的!

以同样的方式,让我们设置单个帖子页面的样式。

进入src/templates目录并创建一个名为 的新文件blogPost.module.scss。然后,添加以下样式:

.content {
  h1 {
    font-size: 35px;
    margin: 0 0 10px;
    text-align: center;
  }
}
.meta {
  font-size: 13px;
  display: block;
  text-align: center;
  font-weight: 300;
  margin-bottom: 20px;
}
.featured {
 max-height: 330px;
  margin-bottom: 25px;
}

之后,进入src/templates/blog-post.js文件并导入.scss文件,如下所示:

import postStyles from "./blogPost.module.scss"

然后,更新语句中的标记return以包含类名。

return (
  <Layout>
    <div className={postStyles.content}>
      <h1>{props.data.markdownRemark.frontmatter.title}</h1>
      <span className={postStyles.meta}>
        Posted on {props.data.markdownRemark.frontmatter.date}{" "}
        <span> / </span> {props.data.markdownRemark.timeToRead} min read
      </span>

      {props.data.markdownRemark.frontmatter.featured && (
        <Img
          className={postStyles.featured}
          fluid={
            props.data.markdownRemark.frontmatter.featured.childImageSharp.fluid
          }
          alt={props.data.markdownRemark.frontmatter.title}
        />
      )}

      <div
        dangerouslySetInnerHTML={{ __html: props.data.markdownRemark.html }}
      ></div>
    </div>
  </Layout>
)

保存您的文件。

您应该看到在单个帖子页面中应用的样式。

添加 404 页面

目前,如果您访问不存在的网站 URL,Gatsby 会将您带到仅在运行开发服务器时才会显示的页面。

在此页面上,您可以单击“预览自定义 404 页面”按钮来查看网站上线时常规用户将看到的实际 404 页面。

现在,单击按钮将指导您如何创建页面。

您所要做的就是创建一个 React 组件页面src/pages/404.js并渲染一些 JSX 元素。

因此,进入src/pages目录并创建一个名为 的新文件404.js。然后,添加以下代码:

import React from "react"
import Layout from "../components/layout"
import { Link } from "gatsby"

const NotFound = () => {
  return (
    <Layout>
      <h1>404: Page Not Found</h1>
      <p>
        <Link to="/blog/">Check our latest articles</Link>
      </p>
    </Layout>
  )
}

export default NotFound

保存文件并重新访问错误页面。

您应该会看到您的自定义 404 页面。

管理页面元数据

每个经过 SEO 优化的网站都会在其 head 元素中包含一些简单的元数据,例如页面标题和描述。这些元数据是帮助搜索引擎理解页面的主要因素,并且对于搜索用户体验也至关重要。

它们用于搜索引擎结果等关键位置。

此外,标题显示在网络浏览器的顶部并充当占位符。

页面元数据

如图所示,文档标题以页面标题开头,后跟分隔符,最后以品牌名称结尾。

但如果你看看我们的 Gatsby 项目,你会发现我们还没有这个。

为了支持它,我们将安装两个包:

停止你的开发服务器并运行以下命令:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > npm install gatsby-plugin-react-helmet react-helmet

react-helmet是一个用于管理文档头的组件。它允许我们设置标题、描述和其他有效的头标签。它gatsby-plugin-react-helmet会将所有这些头标签拉取到我们的 Gatsby 页面中。

接下来,gatsby-plugin-react-helmet添加文件的插件数组gatsby-config.js

反应头盔

启动您的开发服务器并让我们使用这个头盔。

src/components目录中,创建一个名为的新文件metadata.js并添加以下代码:

import React from "react"
import { Helmet } from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

const Metadata = ({ title, description }) => {
  const data = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            description
          }
        }
      }
    `
  )
  const metaTitle = title || data.site.siteMetadata.title
  const metaDescription = description || data.site.siteMetadata.description
  return (
    <Helmet>
      <title>{`${metaTitle} | ${data.site.siteMetadata.title}`}</title>
      <meta name="description" content={metaDescription} />
    </Helmet>
  )
}

export default Metadata

然后进入src/pages目录中每个页面的文件并导入组件来设置元数据。

例如,您的index.js文件应如下所示:

import React from "react"
import Layout from "../components/layout"
import Metadata from "../components/metadata"

const Index = () => {
  return (
    <Layout>
      <Metadata title="Home" description="This is my home page" />
      <h1>Home page</h1>
      <h2>I'm Ibas, a teacher and a Gatsby.js developer</h2>
    </Layout>
  )
}

export default Index

现在,如果您保存文件并检查主页的头部,您应该会看到页面标题和描述。

标题也将显示在浏览器的顶部。

主页元数据

确保Metadata在其他src/pages文件中呈现组件并传递其独特属性titledescription道具。

对于单个帖子页面,标题将根据用户正在查看的帖子动态传递。

因此进入src/templates/blog-post.js文件并导入Metadata组件。

import Metadata from "../components/metadata"

然后,在开始标签之后添加此内容<Layout>

<Metadata title={props.data.markdownRemark.frontmatter.title} />

要在每个帖子页面上显示唯一的描述,您需要description在 Markdown 前置内容中添加一个字段,以便在查询中使用。然后,将其title作为 prop 传递到 中<Metadata />

我们做了什么?

我们首先创建一个可重复使用的组件,Metadata然后在其中配置头盔本身。

该头盔接受纯 HTML 标签(标题和元描述),并将它们输出到文档的 head 元素中。

Metadata通过从每个页面传递 props 数据来访问这些标签的内容。

注意:siteMetadata我们将默认内容设置为文件中指定的数据gatsby-config.js

title与我们设置和的方法相同description,您可以在文档头中设置关键字、作者。

此时,您已经为 Gatsby 网站完成了基本的 SEO 设置。

尝试浏览您的网页并确保网络浏览器顶部的页面标题反映当前页面。

将 Gatsby 站点部署到 Netlify

现在你已经拥有了一个漂亮的网站,是时候把它发布到网络上了。在这里,你将学习如何在 Netlify 上免费托管和部署你的 Gatsby 网站。

Netlify 是一款出色的静态网站托管服务,也是 Gatsby 网站建设的热门选择。它允许我们将代码推送到 GitHub 或其他支持的仓库。然后,它会获取这些代码并部署你的网站。

首先,您需要有一个GitHub 帐户。如果您没有,请创建一个。

然后,我们将所有 Gatsby 文件移动到 GitHub 存储库。

这涉及将文件移动到本地存储库,然后移动到远程存储库。

设置 git 项目时,你要做的第一件事就是初始化你的本地 Git 仓库。这将.git在你的项目目录中创建一个文件夹。

幸运的是,所有 Gatsby 项目都已创建此 Git 仓库。现在你只需确保所有新文件都已添加到该仓库即可。

您将需要几个 Git 命令来实现这一点。

部署到本地存储库

在您的终端中,停止您的开发服务器并运行以下命令:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > git add .

这会将您的所有工作文件保存在暂存区。

要查看暂存区中的内容,请运行以下命令:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > git status

此命令检查工作树的当前状态。如果文件位于暂存区,则显示绿色。否则,显示红色。

接下来,使用以下命令提交所有更改:

C:\Users\Your Name\ ibaslogic-gatsby-tutorial > git commit -m 'first commit'

注意:提交信息用单引号括起来。您可以根据需要进行修改。

此时,您的项目文件现在位于本地存储库中。

部署到远程存储库

继续登录您的 GitHub 帐户并创建一个新的存储库。

GitHub 仓库

在新页面上,您需要为您的存储库命名。在本例中,我将其命名为ibaslogic-gatsby-tutorial。其他字段是可选的,含义不言自明。

请注意,Gatsby 已在你的项目文件夹中包含一个 README.md 文件。因此,请勿使用 README 文件初始化此仓库。

继续并单击创建存储库按钮。

这会将您带到一个可以找到远程 URL 的页面。

找到如下所示的命令并在终端中运行它:

git remote add origin https://github.com/Ibaslogic/ibaslogic-gatsby-tutorial.git

如果找不到,请修改上面的 URL 以反映你的仓库。此命令的作用是将仓库添加为远程仓库。

最后,运行此命令推送到主分支:

git push -u origin master

现在刷新你的 GitHub 页面。你的项目文件和文件夹应该已经推送到你的帐户了。

好的。

我们快完成了!

将 GitHub 存储库连接到 Netlify

前往Netlify 网站并注册一个帐户。确认帐户并登录后,点击屏幕右上角的“从 Git 创建新站点”按钮。

在新页面上,在“持续部署”部分下选择 GitHub 作为您的 Git 提供商,并允许 Netlify 使用您的帐户。

之后,选择您的网站存储库。

这将带您进入部署设置页面。保留默认选项,然后单击“部署站点”按钮开始部署过程。
部署完成后,您将看到站点 URL。

Netlify 网站网址

访问该 URL 即可在网络上实时查看您精美的网站。

伟大的!

更改站点名称

您可以将其更改为易于阅读的名称,而不是使用 Netlify 提供的名称。为此,请转到“设置”选项卡,然后单击“更改站点名称”按钮以指定名称。

就我而言,是 ibaslogic-site

确保保存更改并访问新的 URL。

在这里,我将访问我的网站https://ibaslogic-site.netlify.com/

持续部署

现在,如果您对网站内容或代码进行了更改,只需将其推送到 GitHub 即可在生产环境中查看更改。然后,netlify 将自动触发新的部署,您的更改将在几分钟后生效。

如果您使用的是 VsCode,则可以不使用终端将更改提交到 GitHub。只需按照下图中的标签操作即可。

持续部署

点击“源代码管理”标签 1,查看待处理的更改。然后点击标签 2,显示更多选项。然后,暂存所有更改。完成后,编写提交信息并提交更改。最后,推送到远程存储库。

然后...你就完成了!

结论

恭喜!很高兴你来到这里。这篇文章应该能让你快速了解一下这个主题。

现在你已经了解如何使用 Gatsby 构建静态网站并在 Netlify 上部署。你可以进一步探索所学知识,构建更复杂的项目。

在此之前,请尽力分享这篇文章。

在此处查看项目并在此处查看源代码

如果您有任何问题或贡献,请通过评论部分分享。

下一步是什么?

将您的 Gatsby 网站与CMS(内容管理系统)集成

文章来源:https://dev.to/ibaslogic/gatsby-tutorial-a-step-by-step-guide-to-building-a-gatsby-site-from-scratch-2neh
PREV
React Context API 简化 – 实用指南(更新)
NEXT
调整你的终端