使用 Notion 来进行 Blog 创作
📄

使用 Notion 来进行 Blog 创作

📌
Please Note: This post is pre-release, in order to testing Blog powered by Notion is working. The content is incomplete or may change.
 
在 GitHub 瞎逛时,偶然间发现一个好玩的项目 React-Notion
React-Notion: A React renderer for Notion pages. Use Notion as CMS for your blog, documentation or personal site.
React-Notion 使用 React 进行渲染,并将 Notion 页面转变成个人博客、文档、数据库,甚至是个人网站的工具。
 
立马 Clone 下来,并尝试本地构建他们提供的 Blog Template,发现除了单调的内容,其他什么都没有。
notion image
但是由于是使用 NextJS 作为框架,那就意味着可以使用一些 CSS 来对页面进行美化,参考了一些使用 React-Notion 的例子,便开始使用 tailwindcss 设计属于自己的 Notion Blog。
 
即使我对设计一窍不通,但是 tailwindcss 的写法很简单明了,为我对页面设计减少了不少难度。
 

前车之鉴

我使用过很多基于 Server 的 CMS 和 Serverless 的页面渲染框架,也曾多次修改我 Blog 的渲染框架,但是总是不尽人意。
 

使用 Wordpress 等基于 Server 的 CMS:

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

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

基于 Serverless 简直解决了我的一大痛点,通过各大科技公司提供的内容分发网络(CDN),用户可以借此最快的访问内容。
内容分发网络(CDN):将内容存储在世界各地的服务器上,当用户访问时,利用最近的服务器,将内容传输给用户,以便于达到快速访问的效果。
但是,无论是 Hugo 还是 Hexo,它们都是 Markdown 的渲染器,我在写文章时,需要在 Markdown 上编辑,而当我完成这篇文章时,我需要使用 git 来 push 这篇文章,但是如果我在 GitHub 过多的 push 或者在 vscode 里写 Markdown(我不太喜欢很多软件,喜欢一个软件有很多功能,而不是每一个功能都需要一个软件),都感觉我在水 GitHub Contributions 和 wakatime。
此外,我是一个不懂设计但是又想自己的内容有自己设计风格的人,虽然我很喜欢一些 Hexo 的主题。
 
 

背景 & 参考

自从确定了自己的风格,我就不断挖掘网络上的有趣项目,有时候参考他们,加上自己的元素设计出一些有趣东西,Notion-Blog-React 正是如此。
 
很早就知道 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 服务,免费的 Cloudfalre Workers 每天有 100,000 次访问限制,当然这对普通正常访问绰绰有余。(你可以使用已经由 Splitbee 搭建好的 Notion-API
 
十分意外的,我还翻到了一个也是由 React-Notion 驱动的博客:Spencer's Blog。很喜欢这种自己设计的界面,一对比就知道,我是一点艺术细胞都没有。
 
Super.so 也是一个提供 Notion Blog 的,但是需要额外付费,如果你对编程一窍不通,但是又很喜欢 Notion,不妨尝试以下。
 

起笔

React + Next.JS + tailwindcss + TypeScript,写了一天,大概有那味了,于是公开了第一个版本,嵌套了 notion-api-worker + React-Notion,这两者都是由 Splitbee 编写的,当然不能忘了使用由 Splitbee 提供的 Analytics 服务。
 
但是有几个缺点确实让我很难忍受,比如 Latex 和 Table of Content 无法显示等,这些是由于 React-Notion 的 Blocks 局限性而导致的,你可以在这里查看他们支持的 Blocks 和不支持的 Blocks。经过简单的对比,最后决定使用 notion-api-worker + React-Notion-X,毕竟 React-Notion-X 支持的 Blocks 比 React-Notion 多一些。
 
第二个版本就这样发布了。
 

缺点

设计

其实设计一点都不完善,有一些动画效果或是过度效果实在是不尽人意。

功能

有些功能其实还是很欠缺的,比如说 Sitemap 和 Tags。
 
 

理解

在此服务下,可以理解为,我们使用 Server + Serverless 为我们的 Blog 提供支持。
首先,Notion 是一个 NextJS 应用,他们使用了 Amazon Web Services 提供 PaaS(平台即服务),对于所有用户来说,他们就是一个 CMS(内容管理系统),和 Wordpress 一样,他们都是 Based on Server 的。
而,无论是 React-Notion 还是 React-Notion-X,它们仅为一个 NextJS 应用。
我们通过 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);
提取出来之后,我们在通过一些方法把他们渲染成可读性文字。
// Using NotionRenderer
<NotionRenderer recordMap={recordMap} fullPage={true} showTableOfContents={true} components={{ code: Code, equation: Equation }}></NotionRenderer>
 
 

考虑

避免读取原 Notion Database 页面

使用 .env 避免原 Notion Database 页面外泄,主要是此页面可能有正在编写或者未发布的内容。
 
 

总结

作为个人博客,简洁的内容和明了的界面对我来说挺重要的,不需要登录功能,不需要一大堆插件帮我驱动这个博客的运行,访问的速度能多快就多快,毕竟“天下武功,唯快不破”。