Featured image of post 拥抱 Gatsby,用 React 搭建完整博客系统(五)—— 从 Strapi 获取数据并生成页面

拥抱 Gatsby,用 React 搭建完整博客系统(五)—— 从 Strapi 获取数据并生成页面

Gatsby 学习记录。

按照之前文章内容,我们已经搭建好了 Strapi 环境,创建了我们网站所需要的内容类型,并添加了测试数据。下一步需要的就是获取 Strapi 中的数据,并使用 Strapi 中的数据渲染页面,本部分内容就将实现这一功能。

前言

按照之前文章内容,我们已经搭建好了 Strapi 环境,创建了我们网站所需要的内容类型,并添加了测试数据。下一步需要的就是获取 Strapi 中的数据,并使用 Strapi 中的数据渲染页面,本部分内容就将实现这一功能。

从 Strapi 获取数据

要从 Strapi 获取数据,我们完全可以通过 GraphQL 查询直接请求 Strapi 接口数据,在后续文章中我们会采用这一方式来实现一些高级功能。但在本部分,我们将借助于 Gatsby 所提供的 Strapi 插件 gatsby-source-strapi 来获取 Strapi 中的数据,具体步骤如下:

首先安装插件:

1
yarn add gatsby-source-strapi

之后在项目根目录下的 gatsby-config 中添加以下内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// In your gatsby-config.js
plugins: [
  {
    resolve: `gatsby-source-strapi`,
    options: {
      apiURL: `http://服务器地址:1337`,
      queryLimit: 1000, // Default to 100
      contentTypes: [`post`, `user`, `tag`],
      // Possibility to login with a strapi user, when content types are not publically available (optional).
      loginData: {
        identifier: "",
        password: "",
      },
    },
  },
]

登录信息暂时不需填写,我们暂未应用到需要登录的数据。

之后重新运行项目,再次查看项目 GraphiQL 资源浏览器,可以看到 Strapi 中的资源已经添加到了数据源中:

gatsby-from-zero-5-graphiql.png

使用 Strapi 数据生成页面

回顾使用本地 Markdown 文件生成页面方式

在本系列文章第三篇中,我们学习了如何使用本地 Markdown 文件生成页面,基本思路是在 gatsby-node.js 中添加 onCreateNode 方法,根据不同的节点类型进行不同的处理,在发现节点为本地 Markdown 文件时,将根据文件路径生成 slug 并添加至数据源,之后在 createPages 方法中查询所有的 slug 并调用 Gatsby API 为每个 slug 生成页面

而要生成页面,我们需要提供一个模板文件(如/src/templates/post.js),在生成页面时,将 id 或其他信息传递至模板文件中,在模板文件中使用 GraphQL 查询即可获取到特定数据,渲染出不同页面。

使用 Strapi 数据生成页面

在生成页面的思路上,使用 Strapi 数据和使用本地 Markdown 文件是一致的,实际上还更加简单,因为我们不再需要通过获取文件路径来生成 slug ,而是直接查询 GraphQL 数据即可。

修改 gatsby-node.js 文件

onCreateNode 方法中,我们之前使用了 gatsby-source-filesystem 插件所提供的 createFilePath 方法生成了 slug,并使用 createNodeField 方法将其添加到了数据源中。查看我们在上一节中所创建的 post 内容类型,我们包括了 url 字段,这一字段就是我们所需要的 slug,所以整个 onCreateNode 方法中的内容我们都不再需要,置空即可,没有直接删除是方便之后添加其他方法:

1
2
3
exports.onCreateNode = ({ node, getNode, actions }) => {
  if (node.internal.type === `StrapiPost`) {}
}

继续看下方的 createPages 方法,我们查询了所有的 Markdown 文档的 slug,并为每一个 slug 生成了页面,生成页面时,我们传递了 slug 值至模板文件中,使用 Strapi 数据后,我们对其进行简单调整如下:

 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
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query {
      allStrapiPost {
        edges {
          node {
            id
            url
          }
        }
      }
    }
  `)

  result.data.allStrapiPost.edges.forEach(({ node }) => {
    createPage({
      path: node.url,
      component: path.resolve(`./src/templates/post.js`),
      context: {
        // Data passed to context is available
        // in page queries as GraphQL variables.
        id: node.id,
      },
    })
  })
}

完全参考了使用本地 Markdown 文档时的模式,只不过将页面路径由 slug 换成了 url ,同时向模板文件传递了 id,整体仍然非常清晰。

修改模板文件

我们还需要修改模板文件(/src/templates/post.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
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"

export default ({ data }) => {
  const post = data.strapiPost
  return (
    <Layout>
      <div>
        <h1>{post.title}</h1>
        <div>{post.content}</div>
      </div>
    </Layout>
  )
}

export const query = graphql`
  query($id: String!) {
    strapiPost(id: {eq: $id}) {
      content
      title
    }
  }
`

访问我们生成的页面:

gatsby-from-zero-5-page-no-markdown.png

你会发现,我们在 Strapi 中添加内容时,content 字段添加的是原始 Markdown 内容,这里并不会将其渲染为 HTML,而是原样输出了,这要怎么办?

在渲染本地 Markdown 文档时,我们使用了 gatsby-transformer-remark 插件,该插件将本地 Markdown 文档加入数据源时,会生成一个 html 字段,表示的是 Markdown 文档对应的 HTML 内容。而现在我们需要单独的 Markdown 渲染引擎来进行这样的处理,这里我们使用 React-markdown,使用之前先进行安装:

1
yarn add react-markdown

插件的使用非常的简单,在页面中引入,并使用组件标签将需要渲染的 Markdown 内容包裹即可,在后期进行页面样式优化时,我们再进一步了解其使用方式。

初次使用时,发现存在图片过大的问题,经搜索找到了处理方式,在下方所提供的示例文件内容中已经包括

修改模板文件 /src/templates/post.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
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import ReactMarkdown from 'react-markdown'

export default ({ data }) => {
  const Image = props => {
    return <img alt="" {...props} style={{maxWidth: '100%'}} />
  }
  const post = data.strapiPost
  return (
    <Layout>
      <div>
        <h1>{post.title}</h1>
        <ReactMarkdown
          source={post.content}
          renderers={{image: Image}}
        />
      </div>
    </Layout>
  )
}

export const query = graphql`
  query($id: String!) {
    strapiPost(id: {eq: $id}) {
      content
      title
    }
  }
`

之后再打开之前的页面,已经一切正常了。

gatsby-from-zero-5-page-with-markdown.png

总结

本部分我们参考之前使用本地 Markdown 文档生成页面的思路实现了使用 Strapi 数据生成页面的功能,现在我们可以通过 Strapi 来管理我们的文章,添加文章后,重新进行构建发布就可以同步数据了,实现了将内容与样式的分离。

在目前为止,除后台管理功能之外,我们要实现的主体功能已经全部实现,下一部分开始,我们就对我们的网站进行整体规划,并开始撰写样式。

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