折腾 Gatsby 搭建个人博客

发表于 2023-01-24

为什么搭建个人博客

为什么需要搭建个人博客?这个问题有很多答案,每个人的答案可能不太一样。就我而言,我希望的是分享我的笔记也方便自己查阅,当然这是主要原因并不是唯一原因。

之前也折腾过其他的博客系统(轻度用户),例如 WordPress、B3log/Solo。

最近发现了 Gatsby 这个基于 React 构建的网站生成器,拥有很高的可定制性让我很喜欢,所以我决定将我的博客使用 Gatsby 搭建一遍。

Gatsby 项目

虽然我对于前端的了解的不是很多,我还是期望自己动手制作整个博客的页面以及样式,这大概就是越菜越爱玩吧。

所以我选定的 Starter 是 gatsby-starter-hello-world,用于学习也方便结合官方文档(中文文档)理解其基本原理。

说明项目的基本结构,方便组件的统一管理。

  • /src/pages 的组件会生成对应的页面。
  • /src/templates 用于存放的模板组件,例如渲染 Markdown 文章的模板。
  • /src/components 存放一些共用的组件。
  • /static 放置的都是静态资源。

介绍三个比较重要的文件。

  • /gatsby-config.js 用来配置 siteMetadata(全局信息)和 plugins(插件)。
  • /gatsby-node.js 可以调用 Gatsby API 干一些自动化的工作,如:为 Markdown 文章生成自定义路径。
  • /gatsby-browser.js 可以调用 Gatsby 浏览器 API 也可以通过该文件引入全局 CSS 文件。

插件的使用

Gatsby 有着很多的插件帮我们节省了很多精力,这里介绍几个更多的插件需要到官网的插件库查看。

我以 gatsby-starter-hello-world 作为基础项目,扩展安装的插件如下。

npm install --save gatsby-plugin-typography react-typography typography typography-theme-fairy-gates
npm install --save gatsby-source-filesystem gatsby-transformer-remark gatsby-remark-images gatsby-plugin-sharp
npm install --save gatsby-remark-highlight-code @deckdeckgo/highlight-code
npm install --save gatsby-awesome-pagination
npm install --save gatsby-transformer-sharp gatsby-plugin-image

插件的使用流程分为几大部分。

  • 安装:使用 npm install --save xxx 命令安装。
  • 配置:/gatsby-config.js 配置相关插件。
  • 使用:具体页面引入插件的组件进行使用。

Markdown 生成页面

关于插件的使用流程整体上是一致的,我在这里以 Markdown 生成页面所需要的插件为例讲解一下。

涉及的核心插件有如下几个。

  • gatsby-source-filesystem 用于读取项目中的文件。
  • gatsby-transformer-remark 可以将 Markdown 生成 Markdown 节点,节点用于页面的生成。
  • gatsby-remark-images gatsby-plugin-sharp 处理 Markdown 中的图片,否则会导致 Markdown 的图片不可用。

插件的安装命令:npm install --save gatsby-source-filesystem gatsby-transformer-remark gatsby-remark-images gatsby-plugin-sharp

插件的相关配置是在 /gatsby-config.js 文件中。

module.exports = {
    plugins: [
    `gatsby-plugin-sharp`,// 配置的 sharp 插件,用于处理图片的库
    {
      resolve: `gatsby-source-filesystem`,// 读取项目中的文件
      options: {
        name: `src`,
        path: `${__dirname}/src/`,// 指定文件目录
      },
    },
    {
      resolve: `gatsby-transformer-remark`,// 将 Markdown 生成 Markdown 节点
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,// 处理 Markdown 中的图片。相对于其他插件,该插件是给 gatsby-transformer-remark 使用的
            options: {
              maxWidth: 800,
            },
          },
        ],
      },
    },
  ],
}

/gatsby-node.js 中使用 graphql 查询所有的 Markdown,并用 Markdown 节点生成相关的页面。

const { createFilePath } = require(`gatsby-source-filesystem`)
// 自定义 Slug
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,
    })
  }
}
// 创建页面
exports.createPages = async ({ graphql, actions }) => {
    const { createPage } = actions;
    let resultBlog = await graphql(`
        query {
            allMarkdownRemark  {
                edges {
                    node {
                        id,
                        fields {
                            slug
                        }
                    }
                }
            }
        }
    `);
    // Create blog pages
    resultBlog.data.allMarkdownRemark.edges.forEach(({ node }) => {
        console.log("Create page: " + node.fields.slug);
        createPage({
        path: node.fields.slug,
        component: path.resolve(`./src/templates/blog-post.js`),
        context: {
            slug: node.fields.slug,
        },
        })
    })
}

文件 /src/templates/blog-post.js 是博客对应的模板文件。文章篇幅受限,具体的使用可以查看 Gatsby 中文教程

贴出模板文件示例。

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

// Init
export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title,
        author,
        date
      }
    }
  }
`;

const blogPost = ({ data }) => {
  const post = data.markdownRemark
  return (
    <div>
      <strong>{post.frontmatter.title}</strong>
      <div>
        <div dangerouslySetInnerHTML={{ __html: post.html }} />
      </div>
    </div>
  )
};

export default blogPost;

阅读官方文档更容易学习相关知识,Gatsby 的引导教程相对简单,按着教程入门还是没问题的。

完善博客网站

完成了从 Markdown 到页面的转换后,其实核心功能已经完成,余下的就是不断丰富博客系统了。

这里举几个例子,也是丰富博客的方向,我的目的是生成静态博客。

  • 博客的分页页面。
  • 博客的分类页面。
  • 页面的 Header、导航栏、页脚。
  • Markdown 文件的托管等等。

看看效果

以该文章的最终效果作为示例(样式还没做修正)。

这是示例