Vincent Bel's Blog

基于 Gatsby 搭建博客

Post on September 03, 2017

本文首发于 https://blog.datapipeline.com/create-blog-by-using-gastby/

博客搭建有许多的方案可供选择。我们使用了 Gatsby 搭建博客。这篇博客总结了 Gatsby 的一些好处以及开发过程中遇到的一些问题和解决方式。

优点

1. 基于组件开发

Gatsby 使用的是基于 React 组件的开发。基于组件的开发更容易模块化和封装应用。更简单地给博客添加、修改功能。

component-based development

2. 支持离线访问

博客页面在离线是也能访问。(当然,前提是已经访问过此页面)

offline support

3. 自动化响应式图片

对于页面中使用到的图片,Gatsby 会自动生成多种分辨率的图片,并在不同设备上使用相应大小的图片。

responsive images

4. 由模糊到清晰加载图片

图片加载会先显示一个模糊的轮廓图片,在显示原图。(从 MediumFacebook 开始逐渐流行的显示方式)

image placeholder

5. 灵活

Gatsby 使用了插件系统,并且提供了 许多插件。通过插件可以实现许多功能。

灵活选用技术方案

  • 可以使用 JavaScript 或 TypeScript
  • 灵活选用 CSS 技术方案:CSS、Sass、CSS Modules、CSS in JavaScript 等

比如对于 CSS class 名称冲突的问题,BEM 是一个很好的解决方式。但是我很不喜欢这种方式,因为写起来太麻烦了。Gatsby 比较灵活,我可以使用 CSS Modules,直接把 header.css 改成 header.module.css 就可以了。如果你喜欢用一些 CSS in JavaScript(例如:styled-componentsglamor),也可以灵活配置。

灵活的文件结构

  • 可以把 Markdown 文件放到 contents/ 目录下,也可以放到 /src/pages/
  • 可以把博客相关的 Sketch 文件放到此目录下,如果某张图片需要修改,就不会有找不到源文件的烦恼

灵活的内容读写和转化

  • 可以给博客添加 tags
  • 可以给每篇博客设定一个主色调
  • 可以建一个作者列表页

如何搭建

安装 Gatsby CLI:

npm install --global gatsby-cli

Starter Kit

gatsby new [SITE_DIRECTORY] [URL_OF_STARTER]

# 例如:
# gatsby new blog https://github.com/gatsbyjs/gatsby-starter-blog

Gatsby 官网上有 许多 Starter。搭建博客的话推荐使用功能齐全一些的 starter。也可以使用 本博客使用到的 starter。具体的功能可以直接参考代码实现。

目前,用 gatsby new some-starter-kit 基本过程就是 git fork some-starter-kit,然后再用 npm install(或 yarn install)的安装依赖(相关源代码)。也完全可以手动 fork 一个 starter-kit。

Gatsby 基础架构

Gatsby architecture

Markdown 只是其中的一种源,Gatsby 还支持很多其他源,包括数据库、WordPress、API 等,甚至可以从 medium 上获取数据。

Gatsby 基本目录结构

├── gatsby-config.js              <--- Gatsby 配置(标题、插件等)
├── package.json
└── src
    ├── html.jsx                  <--- 定义基础的 html, head 等
    ├── pages
    │   ├── index.jsx             <--- 首页
    |   ├── about.jsx             <--- about 页面
    │   └── posts                 <--- 具体的博客
    │       ├── 01-01-2017
    │       │   └── index.md
    │       ├── 01-02-2017
    │       │   └── index.md
    │       └── 01-03-2017
    │           └── index.md
    ├── templates                 <--- 模板(博客模板等)
    │   └── post.jsx
    │
    └── layouts                   <--- 页面布局(可以包含 header/footer 等部分)
        └── index.jsx

Markdown 格式规范化

Update: Prettier 现已支持格式 Markdown 文件,推荐直接使用 Prettier 进行格式化。

Markdown 中许多语法都支持多种形式,比如对于无序列表元素,可以使用 -*+。对于多人协作的博客,规范化博客内容能保值一致性,也有助于增加可读性。同时,我们的博客排版规范大致使用 中文文案排版指北。为了让排版更加方便,能自动格式化的地方尽量自动化。

我们使用了 remark 格式化 Markdown 文件,同时写了一个插件 remark-pangu 自动在中英文间添加空格。在每次 git commit 前,都会自动对 Markdown 文件进行格式化。具体处理方式如下。

npm install --save-dev husky lint-staged remark-cli remark-frontmatter remark-pangu

# 或者使用 Yarn
# yarn add --dev husky lint-staged remark-cli remark-frontmatter remark-pangu

package.jsonscripts 部分添加:

"scripts": {
  "precommit": "lint-staged",
}

husky 可以让你在 npm scripts 里写 Git hooks。所以以上配置会在每次 commit 前运行一次 lint-staged 命令。

同时添加 lint-staged 字段到 package.json 里:

"dependencies": {
},
"lint-staged": {
  "src/**/*.{md,markdown}": [
    "remark --output --config",
    "git add"
  ]
},
"scripts": {
}

lint-staged 可以让你对 Git staged 文件运行命令。
例如: Git staged 有两个文件:src/pages/post-a/index.mdsrc/pages/post-b/index.md,在 git commit 时,lint-staged 会运行以下命令:

  • remark --output --config /Users/.../src/pages/post-a/index.md
  • git add /Users/.../src/pages/post-a/index.md
  • remark --output --config /Users/.../src/pages/post-b/index.md
  • git add /Users/.../src/pages/post-b/index.md

remark 命令中,--output 后不加参数会覆盖源文件,--config 搜索配置文件(rc 文件或 package.json 中的 remarkConfig 字段)。

--config 配置其实 默认就是开启的,这里加上只是为了让 --output 能正确使用。--output 后面可以加路径,表示格式化或保存的路径,也可以不加,不加则覆盖源文件。如果这里不加上 --config,组 lint-staged 的命令会变成:

remark --output /Users/.../src/pages/post-a/index.md

会将输入文件(/Users/.../src/pages/post-a/index.md)指定为 output 路径,出问题。所以加了一个实际没什么作用的 --config

package.json 中添加一个 remarkConfig 字段,添加 remark 配置和需要的插件:

{
  // ...
  "remarkConfig": {
    "settings": {
      "bullet": "*", // 无序列表使用 `*`
      "listItemIndent": "1" // 嵌套的列表元素使用 1 个空格
      // 更多配置可以查看:
      // <https://github.com/wooorm/remark/blob/master/packages/remark-stringify/readme.md#processorusestringify-options>
    },
    "plugins": [
      "remark-frontmatter", // 因为我们有用到 Front Matter,所以需要这个插件
      "remark-pangu"
    ]
  }
}

package.json 中实际不支持注释,以上只是为了说明而添加的注释,使用时要将注释去掉。

lint-staged 只能对 Git staged 文件运行命令,如果要对所以 Markdown 文件进行一次格式化,可以使用以下命令:

./node_modules/.bin/remark ./src --output

最终效果:

Markdown auto format

不足之处

🐛 bugs…

还不是很完善,经常会遇到 bug。我在搭建的过程中就遇到了几个 bug(service worker bugPrism bug)。不过这也是一步步完善的过程。

🔍 搜索

如果想做一个搜索所有博客内容的功能,就比较难实现。因为是静态网页,没有数据存储。但也不是不可以,可以使用类似于 Algolia 的第三方服务实现。

🌅 生成的图片名称

目前默认 build 之后的图片名称都是用 hash 来命名,例如 4e1d67ed07986e3edb3dcefd709b478c-6f08c.png。如果能保留原文件名称会更具可读性一些,例如 datapipeline.e1d67ed0.png


参考资料

  1. https://www.gatsbyjs.org
  2. https://github.com/wooorm/remark