Featured image of post 拥抱 Gatsby,用 React 搭建完整博客系统(二)—— 从本地文件获取数据

拥抱 Gatsby,用 React 搭建完整博客系统(二)—— 从本地文件获取数据

Gatsby 学习记录。

在本系列文章的第一篇中,我们已经成功搭建了我们的 Gatsby 网站。我们可以随意的使用 React 为网站添加页面,但我们的网站不可能完全依赖于我们手写每一个页面,我们需要外部数据的参与。 本篇内容就将讲述如何让 Gatsby 读取到本地文件,我们的目标是从本地读取文件,并将文件列表展示在页面中。

前言

在本系列文章的第一篇中,我们已经成功搭建了我们的 Gatsby 网站。我们可以随意的使用 React 为网站添加页面,但我们的网站不可能完全依赖于我们手写每一个页面,我们需要外部数据的参与。

本篇内容就将讲述如何让 Gatsby 读取到本地文件,我们的目标是从本地读取文件,并将文件列表展示在页面中,在实现这一目标之前,我们必须一起学习一些必要的知识。

Gatsby 中的数据

在 Gatsby 中的数据,可以简单理解为“所有在 React 组件之外的东西”。

数据可以是任何来源的,可以来自于本地文件,可以来自于 Wordpress 或者 Strapi 等提供的 API。即便是本地文件,也可以是任何格式,可以是 Markdown 文档,也可以是 CSV 数据————当然这里有一个前提,你要能找到特定的插件来解析你需要的文件。

我们可以以 Webpack 中 loader 的概念来类比,Webpack 可以解析任何文件——如果有支持这一扩展名的 loader 的话。

使用 GraphQL

Gatsby 的数据层由 GraphQL 驱动,有兴趣学习 GraphQL 可以前往官方文档中推荐的网站:如何学习 GraphQL

GraphQL 并非必须使用,如果你要搭建的网站内容非常简单,可以选择直接使用 createPage API 将数据提取到页面,官方提供了一个不使用 GraphQL 的示例,可供参考,但本文将坚定不移的使用 GraphQL 这一面向未来的技术,下面就简单看一下如何在 Gatsby 中进行 GraphQL 查询。

在页面中查询

还记得我们在上文中展示的 GraphQL Explorer 的截图吗? gatsby-from-zero-1-4.png

我们发起了一个查询,查询了站点元数据(存储在 gatsby-config.js 中)的网站标题和网站简介,我们就利用这一查询得到的数据来生成一个新的 about 页面。

pages 目录下创建 about.js 文件,内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"

const About = ({data}) => (
  <Layout>
    <h1>About {data.site.siteMetadata.title}</h1> {/* highlight-line */}
    <p>
      {data.site.siteMetadata.description}
    </p>
    <Link to="/">Go back to the homepage</Link>
  </Layout>
)

export default About

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
        description
      }
    }
  }
`

之后打开http://localhost:8000/about,就能看到我们已经成功将数据渲染到了页面中。

gatsby-from-zero-2-1.png

从上面页面的内容可以看出,页面查询定义在组件之外(一般在页面组件文件的最后),并且只在页面组件中可用,GraphQL 查询的加入没有破坏 React 文件的结构,这非常好。

在非页面中查询

在非页面中查询是需要使用 Gatsby 提供的 StaticQuery 特性,在 React Hooks 日趋成为主流的情况下,Gatsby 也提供了 useStaticQuery 强化了这一特性,本文均将使用最新的 useStaticQuery 语法。

新旧两种写法的对比可以查看官方文档,新写法与页面查询更加一致。

我们同样以查询页面标题和说明为例,展示一下 useStaticQuery 的使用,查看我们使用的示例中的 /src/components/layout.js 文件内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"

import Header from "./header"
import "./layout.css"

const Layout = ({ children }) => {
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)

  return (
    <>
      <Header siteTitle={data.site.siteMetadata.title} />
      <div
        style={{
          margin: `0 auto`,
          maxWidth: 960,
          padding: `0px 1.0875rem 1.45rem`,
          paddingTop: 0,
        }}
      >
        <main>{children}</main>
        <footer>
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.org">Gatsby</a>
        </footer>
      </div>
    </>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

可以注意到,这一页面使用了 useStaticQuery,可以很明显的看到,与页面查询不同的是,必须将查询语句通过 useStaticQuery 包裹,并且写在组件内部,不过整体仍不失清晰。

在页面中同样可以使用 useStaticQuery,可以让你的页面看起来更 React 一些。

使用 GraphiQL Explorer

GraphiQL Explorer 是 GraphQL 提供的一款资源可视化查询工具,可以检查 GraphQL 的语法,发送 GraphQL 的请求,还提供文档查询等功能。Github 最新的 v4 版本的 API 就全面转向了 GraphQL,可以访问这里体验,Gatsby 运行时同样运行了一个 GraphiQL Explorer 实例,可以通过访问 http://localhost:8000/__graphql 体验。

读者可以通过这一工具来体验一下 GraphQL 的使用。

读取本地文件内容

借助于 Gatsby 强大的插件,要实现这一功能非常简单,简而言之:使用 gatsby-source-filesystem 插件将本地文件转换为 Gatsby 数据,用户直接通过 GraphQL 查询数据进行使用。

安装配置 gatsby-source-filesystem 插件

使用 yarn add gatsby-source-filestystem 安装插件,之后我们在 gatsby-config.js 文件中进行配置。

将以下代码添加到 gatsby-config.js 文件中的 plugins 数组中:

1
2
3
4
5
6
7
  {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },

我们使用的起始模板中,已经包括了 gatsby-source-filesystem 插件,不过只解析了 /src/images 目录,我们再后面添加解析 /src 目录,就可以获取到全部文件了。

由于代码中依赖对 images 目录的解析,这里不直接修改目录,而是增加目录,gatsby-source-filesystem 可以分别解析多个目录。

重新启动开发服务器,前往 GraphiQL Explorer 中查询,可以看到 src 目录中所有文件都已经在数据源中了:

gatsby-from-zero-2-2-with-filesystem.png

使用 gatsby-source-filesystem 插件

我们创建一个页面,来展示一下我们 src 目录下都有哪些文件,我们直接参考官方示例,要展示的字段可以根据 GraphiQL 中查询到的信息任意替换。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"

export default ({ data }) => {
  console.log(data)
  return (
    <Layout>
      <div>
        <h1>My Site's Files</h1>
        <table>
          <thead>
            <tr>
              <th>relativePath</th>
              <th>prettySize</th>
              <th>extension</th>
              <th>birthTime</th>
            </tr>
          </thead>
          <tbody>
            {data.allFile.edges.map(({ node }, index) => (
              <tr key={index}>
                <td>{node.relativePath}</td>
                <td>{node.prettySize}</td>
                <td>{node.extension}</td>
                <td>{node.birthTime}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </Layout>
  )
}

export const query = graphql`
  query {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`

打开 http://locahost/my-files页面,就可以看到效果:

gatsby-from-zero-2-3-my-files.png

总结

通过本篇内容,我们了解了 Gatsby 中的数据,并且了解了如何获取项目目录中的文件,但目前只有文件本身的信息,却无法获取文件内容,要获取文件内容并将其转换为数据源,就需要数据源转换插件的帮助了,下一部分我们就将实现这一功能。

comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计