你可以很容易地将你的想法发布到Dev.to、Hashnode或Medium等网站上,但最理想的是完全控制你自己的内容。现在有一个不断增长的工具清单,用于建立你自己的网站和控制你自己的内容。在这个广泛的教程中,我将介绍如何使用Gatsby使你的内容大放异彩,并在这样一个生态系统中得到更多的钟声和口哨。
我最初使用Jekyll来发布我的博客,但后来改用Gatsby,使用Lumen模板。我从0版本开始使用Gatsby,大约在2017年5月。
我将从一个Hello, World! Gatsby项目,通过代码语法高亮和主题切换来实现这种黑暗模式的好处,成为一个编码博客。
Gatsby有一个丰富的插件、启动器和主题的生态系统,可以让你快速启动和运行,但我想采取渐进式披露的方法来介绍Gatsby,重点是Gatsby项目如何运作的基本原理。
为什么是Gatsby?
Gatsby是一个静态网站生成器,所以当页面被请求时,没有动态生成的页面。Gatsby网站的构建输出可以托管在CDN上,使其在全球范围内可用,并具有超级可扩展性。
Gatsby可以使用Markdown文件来创建网站项目中的页面。Gatsby会将Markdown文件读入Gatsby文件系统,并将Markdown转化为HTML,然后在构建网站时创建静态页面。
最终的结果是一个超级快速的网站,在请求页面时几乎没有延迟。
马克笔和MDX
自2016年以来,我一直在用Markdown记录我的开发历程。Markdown提供了一种在纯文本文件中实现简单编辑的方式,可以转换为HTML。
MDX(或Markdown JSX)是一种工具,可以让你在Markdown文档中编写JSX,有点像这样。
import { RainbowText } from './components/rainbow';
## A Markdown Heading
<RainbowText>Wheeeeeeee</RainbowText>
Gatsby是迄今为止我使用过的最好的Markdown和MDX的框架,因为在你的文章上使用frontmatter,不需要特殊的符号。
我需要什么?
如果你打算跟着做,你需要一些东西。
- 一个基本的网络开发设置。Node、终端(bash、zsh或fish)。
- 一个文本编辑器
- 对React的基本了解
如果你没有这些东西,StackBlitz和GitHubCodespaces都有,你可以在那里创建一个空的GitHub仓库,然后从那里开始使用开发环境。
在下面的例子中,我将使用VS Code作为我的文本编辑器,Yarn作为我的首选软件包管理器。如果你喜欢npm,那也很酷。👍
好了,是时候开始了!
你好,世界!
现在是时候启动一个Gatsby项目了。我将从命令行开始做大部分的工作。
# create the project directory
mkdir my-gatsby-blog
# change into the directory
cd my-gatsby-blog
# initialise a package.json file
yarn init -y
# initialise the git repo
git init
酷,现在,在进行其他工作之前,我需要在安装任何npm模块之前添加一个.gitignore 文件。
# create .gitignore file in my directory
touch .gitignore
# add ignore contents with echo
echo "# Project dependencies
.cache
node_modules
# Build directory
public
# Other
.DS_Store
yarn-error.log" > .gitignore
现在我可以安装所有我需要的npm好东西了,而不需要VS Code Git对我大喊大叫,说有太多的活动变化。现在,让我们安装一些依赖项,以启动和运行Gatsby。
yarn add gatsby react react-dom
# -p is to create parent directories too if needed
mkdir -p src/pages
# create the index (home) page
touch src/pages/index.js
接下来,我们将为该项目添加第一个React组件(很多)。我将在我创建的index.js 文件中添加以下内容。
import React from "react";
export default function IndexPage() {
return <h1>Hello, World!</h1>;
}
现在我已经准备好从命令行运行Gatsbydevelop 命令。
# if you're using npm 👇
# $(npm bin)/gatsby develop
yarn gatsby develop
这将启动Gatsby开发服务器,并说我的项目可以在8000端口(Gatsby默认端口)的浏览器中查看。URL是http://localhost:8000/。
直接从命令行界面(CLI)使用Gatsby二进制命令是完全可行的,但大多数人将把可用的命令添加到package.json 文件中的scripts 部分,像这样。
"scripts": {
"build": "gatsby build",
"dev": "gatsby develop",
"serve": "gatsby serve",
"clean": "gatsby clean"
},
作为一个额外的奖励,这里有一些额外的东西可以添加到Gatsby脚本中。
如果我们不想每次都在同一个端口上运行项目,可以用-p 标志来改变它,并在后面指定一个端口。例如,gatsby develop -p 8945 。
如果我们想在项目完成后打开浏览器标签,我们可以在脚本中加入-o 。
我也会对serve 脚本做同样的处理,这样我就知道当我建立一个项目时,它的端口和开发端口是不同的。
"scripts": {
"build": "gatsby build",
"dev": "gatsby develop -p 8945 -o",
"serve": "gatsby serve -p 9854 -o",
"clean": "gatsby clean"
},
就这样,强制性的 "你好,世界!"的欢迎仪式完成了,我可以继续写这篇文章的其他部分了🤓
最后,我将提交我到目前为止所做的修改。
# add everything for committing
git add .
# commit to repo
git commit -m 'init project'
博客的内容
好了,现在这个项目没有什么大的进展,所以首先我将再次从命令行中添加一些内容。
# this creates the folders in the root of the project
mkdir -p content/2021/03/{06/hello-world,07/second-post,08/third-post}
# create individual files
touch content/2021/03/06/hello-world/index.mdx
touch content/2021/03/07/second-post/index.mdx
touch content/2021/03/08/third-post/index.mdx
我将在我所做的整个例子中使用这些内容。
你会注意到文件的扩展名是.mdx 。这是一个MDX文件。
前面的内容
在我为博客添加一些内容之前,我需要谈一谈正面内容。
Front matter是一种存储文件信息的方式,当Gatsby从文件中构建页面时,可以使用这些信息。现在,我将添加文章的title 和date 。我还将为它们添加一些内容。这是我们的第一个帖子。
---
title: Hello World - from mdx!
date: 2021-03-06
---
My first post!!
## h2 Heading
Some meaningful prose
### h3 Heading
Some other meaningful prose
这是我们的第二篇帖子。
---
title: Second Post!
date: 2021-03-07
---
This is my second post!
第三篇帖子。
---
title: Third Post!
date: 2021-03-08
---
This is my third post!
> with a block quote!
And a code block:
```
const wheeeeee = true;
```
这就是目前的帖子,因为这些帖子还没有被Gatsby识别为页面。我需要让Gatsby知道在哪里可以找到添加到项目的内容。为了做到这一点,我将为Gatsby添加一个配置文件。
让我们把我所做的修改提交给Git。
# add changed file for committing
git add .
# commit to repo
git commit -m 'add markdown files'
Gatsby 配置
Gatsby配置是用来定义和配置你可以使用的许多Gatsby插件的。更多关于Gatsby插件生态系统的信息将在稍后公布。现在,我将创建一个文件,还是在终端。
touch gatsby-config.js
这将在项目的根部创建gatsby-config.js ,这样我就可以开始配置Gatsby来读取我之前创建的.mdx 文件。
Gatsby插件
现在我可以安装和配置Gatsby所需的插件,以获得我所创建的文件的来源和显示。我现在将安装它们,并简要地说明它们的用途。
yarn add gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react gatsby-source-filesystem
现在快速看一下package.json ,显示我安装了以下依赖版本。
"dependencies": {
"@mdx-js/mdx": "^1.6.22",
"@mdx-js/react": "^1.6.22",
"gatsby": "^3.1.1",
"gatsby-plugin-mdx": "^2.1.0",
"gatsby-source-filesystem": "^3.1.0",
"react": "^17.0.1",
"react-dom": "^17.0.1"
},
有一点需要注意的是,在Gatsby中,不需要在你的组件中导入React 17。但为了完整起见,也为了避免任何混淆,我将在这些例子中包括它。
现在我需要配置gatsby-plugin-mdx 和gatsby-plugin-mdx 。在gatsby-config.js 文件中,我将添加这个。
module.exports = {
plugins: [
`gatsby-plugin-mdx`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content`,
name: `content`,
},
},
],
};
提交到现在为止的改动。
git add .
git commit -m 'add gatsby plugins'
Gatsby GraphQL
现在是时候通过使用Gatsby GraphQL客户端GraphiQL来看看我在Gatsby中的文件情况了。你可能已经注意到,如果你一直在关注,CLI指出了两个URL位置来查看项目。
You can now view my-gatsby-blog in the browser.
⠀
http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
http://localhost:8000/___graphql
我现在将使用___graphql (三个下划线)路线来查看文件系统中的文件。
如果这看起来有点吓人,我将试图涵盖所有可能看起来没有什么意义的部分。如果你跟上了,你应该可以把例子复制到GraphiQL浏览器中。
当我打开GraphiQL探索器时,我有几个探索器面板。这是项目中所有可供探索的数据,取决于我在gatsby-config.js 文件中的配置。
GraphiQL查询面板和结果就在这旁边。这是我要写GraphQL查询的地方,以检索我需要的数据。在查询面板的底部还有一个QUERY VARIABLES部分,我稍后会讨论这个问题。
在最右边是GraphQL文档资源管理器。由于GraphQL的严格类型化,这意味着它能够生成自己的数据文档。但这不在这篇文章的范围之内。
用GraphQL查询本地文件
接下来,我将在GraphiQL查询面板中查询我先前添加的文件。在这个查询中,我正在查询文件的字体中定义的标题和日期。
{
allMdx {
nodes {
frontmatter {
title
date
}
}
}
}
如果我们把它弹到查询面板上按下大的播放按钮,我们就会在结果面板上得到一些数据。我们也可以使用左侧面板中的资源管理器来挑选数据。这是我运行查询后得到的结果。
{
"data": {
"allMdx": {
"nodes": [
{
"frontmatter": {
"title": "Hello World - from mdx!",
"date": "2021-03-06T00:00:00.000Z"
}
},
{
"frontmatter": {
"title": "Second Post!",
"date": "2021-03-07T00:00:00.000Z"
}
},
{
"frontmatter": {
"title": "Third Post!",
"date": "2021-03-08T00:00:00.000Z"
}
}
]
}
},
"extensions": {}
}
这是一个大的JSON对象,里面有我们在查询中要求的相关信息。我们很快就会看看如何使用这个。现在,这意味着我们可以在Gatsby项目中使用这些数据来制作页面。
网站元数据
在gatsby-config.js 文件中,也有一个选项可以指定网站元数据。网站元数据是为了当我想重用像网站标题和描述这样的普通数据时。
当我想在网站上添加元标签以进行搜索引擎优化(SEO)时,这将是非常有用的。(同样,以后会有更多的内容。)现在,我将在gatsby-config.js ,用siteMetadata 对象来定义网站的一些基本信息。
我可以像这样在module.exports 中直接定义网站元数据。
module.exports = {
siteMetadata: {
title: `My Gatsby Blog`,
description: `This is my coding blog.`,
},
plugins: [
// configured plugins here
{
// empty for brevity
},
],
};
网站元数据对象可能会变得有点大,我发现把它放在自己的对象中可以使它的推理更简单,所以我打算单独定义它。
const siteMetadata = {
title: `My Gatsby Blog`,
description: `This is my coding blog.`,
};
然后将siteMetadata 对象添加到Gatsby配置文件中。
const siteMetadata = {
title: `My Gatsby Blog`,
description: `This is my coding blog.`,
};
module.exports = {
siteMetadata,
plugins: [
// configured plugins here
{
// empty for brevity
},
],
};
现在我可以再次跳到GraphiQL资源管理器上,用下面的查询来查询该网站的元数据。
{
site {
siteMetadata {
title
description
}
}
}
如果你对gatsby-config.js 文件进行修改,停止并重启开发服务器总是一个好主意,所以我将这样做(Ctrl+c,然后是yarn develop ),然后在GraphiQL资源管理器中刷新页面并再次运行查询以获得数据。
{
"data": {
"site": {
"siteMetadata": {
"title": "My Gatsby Blog",
"description": "This is my coding blog."
}
}
},
"extensions": {}
}
制作一个网站元数据钩
现在我在Gatsby文件系统中拥有网站元数据,我可以在任何我想使用Gatsby静态查询钩子的地方查询它useStaticQuery 。我将关闭开发服务器,并在我将以下内容添加到src/pages/index.js 文件后重新启动。
import { graphql, useStaticQuery } from "gatsby";
import React from "react";
export default function IndexPage() {
const {
site: { siteMetadata },
} = useStaticQuery(graphql`
{
site {
siteMetadata {
title
description
}
}
}
`);
console.log("=====================");
console.log(siteMetadata);
console.log("=====================");
return <h1>Hello World!</h1>;
}
关于那里的一些符号的快速说明:const { site: { siteMetadata }, } 是获取site 查询中的数据的快速方法,我从site 对象中提取siteMetadata 。这被称为去结构化。
现在,在我再次启动开发服务器后,我可以到浏览器控制台(在Windows/Linux中是Control+Shift+J,在macOS中是Command+Option+J),在控制台输出中看到siteMetadata 对象。
我得到以下的控制台输出。
=====================
{title: "My Gatsby Blog", description: "This is my coding blog."}
description: "This is my coding blog."
title: "My Gatsby Blog"
__proto__: Object
=====================
不要担心控制台对404页面未找到(net::ERR_ABORTED 404 (Not Found))的警告。我以后再做。
为了避免每次都要写这个查询,我想在一个组件中使用它。我将把它抽象为自己的钩子。
# make a folder for all the hooks to live
mkdir src/hooks
# creathe the file
touch src/hooks/use-site-metadata.js
现在我将在新创建的src/hooks/use-site-metadata.js 文件中加入一个钩子,以按需获得网站的元数据。
import { graphql, useStaticQuery } from "gatsby";
export const useSiteMetadata = () => {
const { site } = useStaticQuery(
graphql`
query SITE_METADATA_QUERY {
site {
siteMetadata {
title
description
}
}
}
`
);
return site.siteMetadata;
};
你可能已经注意到,这个查询与GraphiQL浏览器中的查询不一样。
+ query SITE_METADATA_QUERY {
site {
siteMetadata {
title
description
}
}
}
这是为了给查询命名。因为我将在项目中使用大量的查询,给它们起一个有意义的名字是有意义的。
现在我将在src/pages/index.js 文件中实现新的钩子。
import React from "react";
import { useSiteMetadata } from "../hooks/use-site-metadata";
export default function IndexPage() {
const { title, description } = useSiteMetadata();
return (
<>
<h1>{title}</h1>
<p>{description}</p>
</>
);
}
这样就不那么啰嗦了,而且我可以从SITE_METADATA_QUERY 中挑选我想要的项目。
现在是时候把到目前为止所做的改变记录下来了。
git add .
git commit -m 'add site metadata and metadata hook'