使用 Notion Database 管理静态博客文章

注:本文所有示例代码都可以在 blog-code 仓库中找到

背景

其实在最开始计划的时候,第一篇文章应该是另外一个主题,但是每次开始写文章的时候都忍不住去折腾一下博客(又可以水两篇文章了)

hexo 文章管理

在准备写文章的时候发现 hexo 在文章多了之后管理上很不方便,现在博客也已经有了 150+ 博文了,所有的文章都放在了 _posts 文件夹下面

如上图所示,虽然文章按照分类拆分了文件夹进行管理,但是还是不是特别清晰,毕竟不是所有的文章都是专题文章,还是有一部分笔记或者是其他文章的,在 hexo 中我们给文章分配了标签分类等字段用来区分,但是在实际的文件管理上还是不行

语雀文章管理

之前还在用语雀记录笔记的时候,文章是直接放在了 语雀 上然后通过 yuque-hexo + github actions 自动发布,但是后面将笔记切回 notion 之后,就没用语雀同步了。

可以看到上图,语雀的文章本身是没有其它额外的属性的,所以我们为了支持 hexo 的 yaml frontmatter 就做了一些额外的约定和处理,但是在 notion 的 database 里面这个问题就不存在了,刚刚好可以完美的解决这个问题

方案

ok, idea 有了之后,我们大概想想方案,我大概调研了一下现在存在的主要方案大概可以分为三种

  • 第一种就是,使用 notion database 作为 baas 后端,另写前端页面来获取数据渲染,这种方案的典型代表是 nextjs-notion-starter-kit

    这种方式的主要问题是,在国内的加载速度和不确定性的问题,因为国情原因,notion 访问本身比较慢,并且还存在一些不确定性

  • 第二种和第一种类似,但是第二种方案可以直接生成静态页面,所以就有着和静态博客一样的速度和灵活性,我们可以直接部署在国内。这种方法的典型方式是 Gatsby+Notion

    这种方式的主要问题是主题不够丰富,大概率需要自己修改很多东西才能用,和成熟的 hugo、hexo 比,差的有点太多

  • 第三种方案就是将 Notion Page 转换为 Markdown 文件,然后就可以直接使用 hugo、hexo 等成熟的静态博客生成器了
    这个的主要问题是虽然现在 notion 官方开放了 api,但是没有 api 可以直接将 notion 的数据结构之间转换为 markdown,现在虽然有一些第三方库(例如 notion2md )支持,但是存在着各种各样的问题,要么不支持图片,要么不支持 table 等格式,总是会欠缺一些

经过对比,和当前遇到的问题,我选择了第三种方案,然后自己造个简单的转换轮子

  • 我现在的 hexo 主题使用的还算满意,已经折腾改造过很多次了,不想再改造了(预告一下后面有一篇文章给大家介绍如何使用这个主题给自己的博客也加上左侧的章节目录)
  • 其次是 notion 其实自己可以导出 markdown 文件,我只要使用 notion cookie 调用一下就可以了,工作量其实不是很大,并且后续 notion 即使出其他的 block 大概率也会支持导出,这样我们就不用去单独做兼容了

ok,思路有了,我们看一下最后的方案

  • 使用 Notion Database 作为我们的存储后端
  • Notion Database 中的属性对应到 Markdown 中 YAML FrontMatter
  • 为了避免每次都获取所有的文章数据,我们添加一个 status 字段,当 status待发布 的时候我们才去下载对应的文章,文章下载完成之后,我们就把这篇文章的状态修改为 已发布
  • 由于 notion 的导出 api 导出的文件是一个文件夹,所以我们导出之后需要解压缩
  • 导出的 markdown 文件中,属性的字段会被放在文章的标题下,所以我们需要做一些转换,把它转为 YAML FrontMatter
  • 最后 notion 在导出文件的时候如果里面包含了图片,会创建一个文件夹,我们需要把文件夹中的图片移动到我们需要的目录,例如统一放到 img 目录下

使用

具体代码就不贴了,也没有几行,看下最后的成果就行了(这篇文章就是)我们使用 github action 作为流水线组件,现在我们的工作流就变成了

1
idea -> 放入收集箱 -> 编写文章 -> 移动到待发布 -> 点击执行 github workflow -> 自动发布

相关仓库 & 示例如下

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
on: [workflow_dispatch, watch]

name: notion

jobs:
notion:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
submodules: false

- uses: mohuishou/notion-blog-actions/notion@main
with:
token: ${{ secrets.NOTION_TOKEN }}
token_v2: ${{ secrets.NOTION_TOKEN_V2 }}
space_id: "输入你的空间 id"
database_id: "输入你的 database id"
output: "./tmp/"

- name: "migrate image"
uses: mohuishou/notion-blog-actions/migrate@main
with:
input: "./tmp/*.md"

- name: "cp md files"
run: |
cp -f tmp/*.md source/_posts/notion/
rm -rf tmp

- name: git setting
run: |
git config --global user.email "你的邮箱"
git config --global user.name "你的用户名"

- name: update blog
run: |
git add source
git commit -m "feat: auto update by notion sync"
git push

关注我获取更新

wechat
知乎
github

猜你喜欢


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处,禁止全文转载