我用 Notion 写博客已经一年了,主要是非常方便,想到什么可以先打个草稿,也不用像之前写 Markdown 一样要关心图片和附件的问题。
最近花了一两天终于把小博客打理得比较像样了,便把这折腾过程记录下来。
Notion 官方提供的页面,虽然效果是最好的,但给人的感觉还是笔记页面,而不是真正的「网站」,也不能添加自定义的功能,例如评论,要把 Notion 作为真正的 CMS 来用,可以通过 Notion API 获取数据(作为后端),而我们自己去实现一个前端。
为了减少重复造轮子,我选择了 https://github.com/transitive-bullshit/nextjs-notion-starter-kit ,因为这是一个采用了 Next.js 的框架,而我本人对 React 也略有了解,修改起来比较容易。
这个框架的使用也非常简单,只需要 fork 一份到自己的仓库,再修改 site.config.ts
中的网站设置,使用 Vercel 即可部署一个网站,如果你不怎么想折腾,到这里就差不多结束了。
是的,虽然 Next.js 是 Vercel 所开源,对 Next.js 的构建部署也非常方便,为什么我还要选择自建呢?
自从去年 nextjs-notion-starter-kit 的作者加入了图片优化之后,我常常能收到 Vercel 的滥用警告。
而事实是,我的图片数量远没有那么多,我也很少重新构建项目(后来知道是因为每次请求了签名的文件链接,导致图片无法被缓存,下文有解决办法),但一直超过用量不是个好兆头,我也承担不起 Vercel 高昂的费用(相比起很多服务器来说),于是决定把博客迁移到自建服务器上。
因为之前没有接触过 Next.js ,查询了一下资料发现部署是比较简单的,nextjs-notion-starter-kit 使用的是 SSR ( Server Side Render ,服务端渲染),只要把服务器用 Node.js 跑起来就可以了。
然而,我对这个框架做了较多的修改,如果用之前的「 fork-sync-修改-部署」流程,很容易产生冲突,于是我想到了一种比较方便的办法:用 GitHub Actions 拉取最新代码,用我自己修改的文件覆盖原作者的代码,再打包成 Docker image 。我已经在 GitHub 开源: https://github.com/imbytecat/nextjs-notion-starter-kit-docker ,需要的可以自己 fork 修改。
由于前端都由我们自己掌控,要做一些功能的更改非常容易。
原版框架的页面右上角会添加一个指向开源项目的按钮,而且不能简单通过配置文件设置不显示。
在阅读代码之后发现,这个按钮封装成了一个组件,而且确实没有相关的设置来移除,只能通过删除代码解决:
这样重新构建后就不会显示分享按钮了。
参考了 WeijunDeng 的修改建议,不过因为时间较久,但目前其代码依然可以使用。
只需要在 lib/notion.ts#L42 处加入以下代码:
if (recordMap && recordMap["signed_urls"]) {
const signed_urls = recordMap["signed_urls"]
const new_signed_urls = {}
for (const p in signed_urls) {
if (signed_urls[p] && signed_urls[p].includes(".amazonaws.com/")) {
console.log("skip : " + signed_urls[p])
continue
}
new_signed_urls[p] = signed_urls[p]
}
recordMap["signed_urls"] = new_signed_urls
}
这样图片就会变成永久链接,不会每次都带着签名请求 Notion API ,也能正确触发图片缓存,但不知道为什么原作者迟迟不合并这个请求。
使用 UUID 作为路径的原因很简单:
完成后的效果:
https://www.imbytecat.com/2f3456133af0425da87539dd6a8b2379
方法也很简单,只需要将 lib/get-canonical-page-id.ts#L23 替换成:
return getCanonicalPageIdImpl(pageId, recordMap, { uuid: true }).split('-').slice(-1).join('')
另外不要忘了在 lib/get-canonical-page-id.ts#L12 上方加一句 // eslint-disable-next-line @typescript-eslint/no-unused-vars
,否则过不了 ESLint 检查,不能构建成功。
评论系统我用的是 Waline ,以前用过 Valine 还不错,但是有纯前端实现有安全问题,并且非常依赖 LeanCloud ,而 Waline 可以自建。
评论的实现比较粗糙,还没来得及调整样式,所以还存在一些问题,不过大概的思路可以讲一下。
如果使用 Waline ,需要先添加依赖:
yarn add @waline/client
yarn add sass
首先可以新建一个 components/Comment.tsx
作为我们的评论框组件,内容大概是这样:
import { init } from '@waline/client';
import '@waline/client/dist/waline-meta.css';
import '@waline/client/dist/waline.css';
import React, { useEffect, useRef } from 'react';
import type { WalineInitOptions, WalineInstance } from '@waline/client';
export type WalineOptions = Omit<WalineInitOptions, 'el'> & { path: string };
export const Waline = (props: WalineOptions) => {
const walineInstanceRef = useRef<WalineInstance | null>(null);
const containerRef = React.createRef<HTMLDivElement>();
useEffect(() => {
walineInstanceRef.current = init({
...props,
el: containerRef.current,
});
return () => walineInstanceRef.current?.destroy();
});
useEffect(() => {
walineInstanceRef.current?.update(props);
}, [props]);
return <div ref={containerRef} />;
};
然后在 components/NotionPage.tsx
使用就可以了:
import { Waline } from './Comment'
// ...
{block.id.replace(/-/g, '') !== site.rootNotionPageId ?
<Waline
serverURL='https://waline.imbytecat.com'
path={'/' + block.id.replace(/-/g, '')}
emoji={[
'//cdn.jsdelivr.net/gh/walinejs/[email protected]/tw-emoji'
]}
dark={isDarkMode}
meta={['nick', 'mail']}
requiredMeta={['nick', 'mail']}
imageUploader={false}
copyright={false}
/> : null}
// 放在这个结束标记前面
</>
最终应该可以得到和 🎉 效果展示 差不多的样子。
1
CrazyCoolL 2023-02-02 11:56:46 +08:00 via iPhone
直接使用 Notion 本身其实就挺好的,我的个人主页: https://imllf.com
|
2
lifesimple 2023-02-09 10:41:09 +08:00
@CrazyCoolL 强啊 老哥能写篇文章分享下是怎么搭建的么,纯 notion 搭建?改过样式么 另外就是留言板输入中文容易失焦
|
3
CrazyCoolL 2023-02-09 17:30:11 +08:00
@lifesimple 对,纯 Notion 搭建,只有留言部分是嵌入了其他页面。(好像是有失焦问题,怪)
|
4
Laussan 2023-02-19 02:58:43 +08:00
马一个,小白想问几个问题:
CMS 具体是指什么? Notion API 获取的是什么类型的数据?是会完整拉取到服务器端么? 跑这个的 vps 大概需要什么配置? 提前感谢! |
5
ByteCat OP @Laussan 可以看下 [Wikipedia 的说明]( https://zh.wikipedia.org/zh-cn/%E5%86%85%E5%AE%B9%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F),Notion API 可以获取 Notion 的所有数据,所以可以据此复刻一个 Notion 出来,也可以用 API 来实现一个 CMS ,我用的方案就是 [nextjs-notion-starter-kit]( https://github.com/transitive-bullshit/nextjs-notion-starter-kit),是一个基于 Next.js 的框架。
跑的话,配置要求不高,随便一个服务器应该都可以,嫌麻烦可以直接用 Vercel 的,甚至不需要服务器。 |
6
foyo 2023-02-26 01:38:46 +08:00
可以不购买 VPS ,直接用 GitHub Pages 部署,具体可以参考 https://xchb.fun/%E7%94%A8notiongithub-pages%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%8D%9A%E5%AE%A2
|
7
ByteCat OP @foyo 静态生成也不错,不过我图片都用 Cloudflare 缓存了,所以很快,Notion API 请求多了好像有限制。
|
8
Anjhon 2023-05-09 16:55:32 +08:00
这个我必须来推荐 NotionNext 一波,完美契合你的需求,博客功能完善,而且作者还在持续更新; GitHub 地址: https://github.com/tangly1024/NotionNext ;打个广告(我的博客地址😂):anjhon.top
|