使用 Notion 来进行 Blog 创作

前言

自从发现 Notion 这个软件后,就爱不释手了。生活上的记录都使用 Notion 来管理,这极大程度上提高了我学习、生活和工作上的效率。正因为如此,您所看到的此篇文章,应该说是整个 Blog 就是从 Notion 生成的。

发现

使用 GitHub 时,偶然间发现一个与 Notion 相关的项目 React-Notion,其使用 React 进行渲染,可以将 Notion 页面转变成个人博客、文档、数据库,甚至是个人网站,其转换出来的页面几乎是翻版 Notion。

由于并没有 Demo Link,所以立马 Clone 下来,并尝试在本地构建他们提供的 Blog Template,发现除了单调的内容,其他什么都没有,不过这就已经足够了。
由于是使用 NextJS 作为框架,那就意味着可以使用一些 CSS 来对页面进行美化,参考了一些使用 React-Notion 的例子,便开始使用 tailwindcss 设计属于自己的 Notion Blog。
使用 tailwindcss,即使对设计一窍不通,但 tailwindcss 的用法很简单明了,为我对页面设计减少了不少难度。

前车之鉴

我使用过很多基于 Server 的 CMS(如 Wordpress) 和 Serverless 的页面渲染框架(如 Hugo),也曾多次修改我 Blog 的渲染框架,但是总是感觉达不到理想的效果,希望自己的 Blog 能既简洁又有自己的风格。

使用 Wordpress 等基于 Server 的 CMS

虽然 Wordpress 的插件很多,总能找到喜欢的插件来使博客光鲜亮丽,但是正是因为插件多且复杂,导致原本只想要简洁的博客变得繁杂且臃肿。此外,使用 Wordpress 需要及时管理插件的更新,而数据库的管理更是头痛。如果你是团队或者公司的博客网站,Wordpress 绝对是不二之选。再者,由于 Wordpress 是基于 Server 和 Database 的一个产品,所以在不同地点的访问速度也不同,很大程度的造成了部分地区访问困难的情况。虽然我们可以套用 Cloudflare CDN 使其在全球大部分地区的访问速度变快,但是服务器的配置始终是硬伤。这也是我在使用了几个月的 Wordpress 而放弃的一大原因。

使用 Hugo、Hexo 等基于 Serverless 的静态页面渲染框架

基于 Serverless 简直解决了我在使用 Wordpress 上的一大痛点,通过类似如 Vercel 提供的内容分发网络(CDN),用户可以借此最快的访问网站上的内容。
虽然我不懂设计,但是又想 Blog 有自己设计风格,虽然我很喜欢一些 Hexo 的主题,但是最终都还是放弃了使用 Hexo。

参考

很早就知道 Fruitionsite,使用 Cloudflare Workers 将 Public Notion Page 转变成可以嵌套个人域名的工具。但是,这只是嵌套,或可以理解为反向代理,但是实际上,Notion 使用的服务,如 Intercom、Sentry 等,即使使用自己的域名,也会同步加载这些服务,这样会使网页加载变慢。如果你不在意这些问题,Fruitionsite 的确是一个不二之选。
React-Notion-X 也是一个和 React-Notion 类似的项目。
与 React-Notion 不同的是,notion-client 是他们主要的 API 服务,而 React-Notion 使用 notion-api-worker,其需要搭配 Cloudflare Workers 和 KV 空间搭建 API 服务,免费的 Cloudflare Workers 每天有 100,000 次访问限制,当然这对普通正常访问绰绰有余。(当然,你可以使用已经由 Splitbee 搭建好的 Notion-API
Super.so 也是一个提供使用 Notion 作为 Blog 的服务,但是需要额外付费,如果你对编程一窍不通,但是又很喜欢 Notion,不妨尝试以下。

起笔

使用 React + Next.JS + tailwindcss + TypeScript 并搭配 notion-api-worker + React-Notion(这两者都是由 Splitbee 编写的),Blog 已经大致成形。但是有几个缺点确实让我很难忍受,比如 Latex 和 Table of Content 无法显示等,这些是由于 React-Notion 的 Blocks 局限性而导致的,你可以在这里查看他们他们是否支持某些 Blocks。经过简单的对比,最后决定使用 notion-api-worker + React-Notion-X,毕竟 React-Notion-X 支持的 Blocks 比 React-Notion 多一些。
经过不断的改动和测试,Notion-Blog-React 终于做了出来。

缺点(日后计划)

使用官方的 Notion API (我们已经完成了完全使用 Notion 官方 API 所构建的博客,希望尽快在将来发布)
Sitemap:目前是手动更改 Sitemap。
Postview
Tag 页面

理解

在此服务下,可以理解为,我们使用 Server + Serverless 为我们的 Blog 提供支持。
首先,Notion 是一个 NextJS 应用,他们使用了 Amazon Web Services 提供 PaaS(平台即服务),对于所有用户来说,他们就是一个 CMS(内容管理系统),和 Wordpress 一样,他们都是 Based on Server 的。
而,无论是 React-Notion 还是 React-Notion-X,它们仅为 Notion React Renderer 应用。简单来讲,我们通过 API 将 CMS 的内容提取到 JSON 中,再通过一定手段,读取这个 JSON,我们的页面也由此产生了。
在这里,无论是 notion-api-worker 还是 notion-client,他们作为我们的 API 去提取 Notion pageID 的内容。
// Using notion-api-worker to get JSON
export const getNotionPosts = async (): Promise<PostContent[]> => {
    return await axios.get(`https://${NOTION_API}/v1/table/${NOTION_PAGE_SLUG}`).then((response) => response.data);
};
// Using notion-client to get JSON
const notionAPI = new NotionAPI();
const recordMap = await notionAPI.getPage(notionPostID);
提取出来之后,我们在通过 Notion Renderer 把他们渲染成可读性文字。
// Using NotionRenderer
<NotionRenderer recordMap={recordMap} fullPage={true} showTableOfContents={true} components={{ code: Code, equation: Equation }}></NotionRenderer>
大功告成。

考虑

使用 .env

请注意:这并不能完全阻止完整地读取 tableID。
由于读取的 Notion Table 可能有未发布的内容,所以需要使用 .env 来避免读取到 Notion tableId

总结

作为个人博客,简洁的内容和明了的界面是十分重要的,不需要和 Wordpress 一样的登录功能,也不需要一大堆插件帮我驱动这个博客的运行,访问的速度能多快就多快,这才是我的 Blog 真正需要的。