记录新博客:nobelium, Vercel, Tailwind CSS 和域名

date
Mar 11, 2022
slug
nobelium
status
Published
tags
Blog
summary
长文预警(一不小心写了一万多字…… 真希望我写论文有这动力)。这几天可能是为了逃避一些现实的压力,我疯狂折腾了几天。用 nobelium 搭建了一个新的博客,折腾了一下 Tailwind CSS,顺便买了一个域名,给自己的博客都上了自己的域名。
type
Post
其实去年的时候我就发现了 nobelium 这个项目,也成功搭建了,但是网站的排版样式我一直想调整一下,但是当时不会也没花时间折腾,这几天我就集中现学现卖折腾了一下。

部署过程

如何搭建在 nobelium 的 README 中已经描述的十分清楚,这里简单叙述一下。首先需要准备的是 GitHub 账号,Notion 账号和 Vercel 账号(可以直接用 GitHub 登录),Fork 一下 craigary/nobelium 这个仓库。
notion image
然后 Duplicate 一下 craigary 提供的 Notion 模板(一个 database)到自己的 Notion 账号,在自己的 Notion 中分享这个 database。
notion image
分享之后需要记录一下自己的 Page ID,每个 database 都不一样,craigary 的这张图说明十分清楚。
notion image
再登录 Vercel,选择新建项目,从 GitHub 中导入刚刚 Fork 的仓库,操作都比较符合直觉,这里就不截图了,然后选择 Next.js 框架。然后,设置好环境变量,名称为 NOTION_PAGE_ID ,内容为自己页面的 Page ID,让 Vercel 自动部署。
框架选择 Next.js
框架选择 Next.js
填写环境变量,分别填写名称和值
填写环境变量,分别填写名称和值
部署成功之后,访问 Vercel 提供的网址,应该就可以看到内容了。这时候可以看看那个模板 database,里面的每个属性的含义应该都很清楚了
  • title: 文章的标题;
  • date: 文章发布的时间,如果留空默认是文章创建的时间;
  • slug: 文章 URL 尾部的字符,也就是 .com/xxx 中 xxx 的部分,建议使用英文,用 - 代替空格,如果使用中文或者空格、标点,会被 UrlEncode 变成一长串,链接会显得很长;
  • summary: 文章简介,会显示在主页标题的底部;
  • tags: 文章标签,可以对文章进行分类;
  • status: 文章状态,只有 Published 状态的文章会在博客公开显示;
  • typePost 会直接显示在主页,Page 只有直接访问 URL 会显示,不会出现在主页文章列表中。
我个人使用了 Notion 的 Group(分组)功能把这个 database 按照 status 进行了分组,这样我能更方便集中管理已经发布和未发布的内容。
notion image
之后,我找了几篇以前写的东西,粘贴到了 Notion 模板里,再回到博客,直接刷新页面就可以看到文章了。

开始自己折腾

blog.config

把自己 Fork 的仓库 clone 到本地,就可以开始折腾了。
按照 README 中的介绍,可以修改 blog.config.js 文件对博客进行第一步的自定义。可以自定义的内容在文件中也有很详细的注释了,不要修改作者注释了 do not change 的地方。这里介绍两个我觉得需要注意的地方。
  • 首先是 email 要记住自己填写了什么,因为和头像有关,后面再详细说明;
  • 其次 comment 我个人选择了 Cusdis 而不是 Gitalk,后面也会详细说明。

头像:Gravatar

默认状态下,nobelium 的头像是 这样的:
notion image
十分眼熟,因为这是 Gravatar 的默认头像。需要到 Gravatar 官网 注册一个账号(用 WordPress)账号也可以,注意这里要用刚才在 email 中填写的邮箱注册,然后按照提示上传头像,成功后等待一会,博客应该就会刷新出自己的头像了。
原理应该就是 nobelium 会自动使用 Gravatar 生成的头像 URL 获取头像,只需要在 https://gravatar.com/avatar/ 后加上注册邮箱的 md5 值,就可以直接获取头像了,在 layout.js Ln45 可以看到。

评论:Cusdis

以前在 Gridea 使用的评论系统是 Gittalk,和仓库绑定后,就可以通过 issue 实现评论功能,可以支持 Markdown,只要有 GitHub 账号就可以评论。但是体验上还是有点沉重,在国内的互联网环境更是经常加载不出来,也有人认为这是对 GitHub 的 issue 功能的误用。但对我来说最难受的部分还是自定义样式比较难。
所以这次在 nobelium 发现 Cusdis 之后就试了试,结果很惊喜。按照官网的介绍,Cusdis 是 Disqus 的轻量开源替代,大小只有 5kb,设置成功后基本上是和网页同步加载成功,而且不需要注册任何账号就可以评论。
notion image
Cusdis 可以选择自己部署,也可以使用官方提供的服务器。只需要在官网注册账号,添加一个网站,记住 data-app-id,并填写到 blog.config.js 对应的位置,如果使用官方提供的服务器,可以直接按照这样填写:
完成后就可以把所有的更改 push 到 GitHub,等待 Vercel 部署完成,就可以刷新查看成果了!

Tailwind CSS

以上是最基本的自定义,但对于我这种折腾的人肯定不能满足,我还是喜欢折腾 CSS。
第一天刚刚搭建好 nobelium 的时候我其实就已经折腾了一下样式,但是由于没有仔细看文档,上来我就修改了仓库里比较明显的 global.css  和 notion.css  两个文件,不管里面本来看不懂的内容,直接配合检查工具直接把自己想用的样式用 CSS 硬写了一些,然后野蛮地加上 !important ,强制生效。然而第二天的时候我仔细看了看 nobelium 的文档,发现 nobelium 在介绍中也说自己使用的是 Tailwind CSS / JIT 框架,方便自定义,于是我就查了一下这个似曾相识的名字,发现我错过了太多,之前的自定义基本也就是野路子,实在不算优雅。
我说说我简单的理解,nobelium 的两个 CSS 文件其实是负责两个部分 global.css 主要负责整体的框架,包括导航栏、首页、footer、文章作者等部分;notion.css 主要负责文章正文部分。可以理解为 nobelium 是为 Notion 中的内容提供了一个展示的框架,正文外的其他内容由 nobelium 生成,然后从 Notion 中取正文内容再通过指定的样式渲染,最终展现一个完整的博客。
回到 Tailwind CSS 上,根据我的理解,Tailwind CSS 提供的是一种快速在 HTML 文件中指定样式的框架,只需要在 HTML 元素中指定一些特定的 class,就可以自动生成对应的 CSS 属性,从而达到不离开 HTML 文件快速实现样式自定义的效果。因此再回到两个 CSS 文件中,其中的内容便似乎可以看得懂了。
Notion 中文社区 SilentDepth 🐧 前辈指出了我这里表达的不妥:
🐧
关于 Tailwind CSS 说一点。Tailwind CSS 本质上 [是] 一个 Utility Class/Atomic CSS 生成工具(目前这个领域里的最优实践),旨在寻求便捷性、复用性和可读性间的最佳平衡。它算不上一个框架,更像是一种最佳实践的实现。开发应用时它非常好用,但到了给 Nobelium 开发主题样式这种场景,我更建议 BEM 风格,因为这个场景下样式本身是需要独立表达业务含义的
谢谢帝企鹅!
举个例子,在 notion.css 文件中我自定义了这些:
由于是在 CSS 中使用 Tailwind,所以选择器的规则和 CSS 一样,然后在 @apply 后的内容就是 Tailwind CSS 的「语法」了。 mb-2 是代表 margin-bottom: 0.5rem; /* 8px */ ,text-left 代表 text-align: left; 。
由于这个 CSS 是调整正文部分,所以我对排版进行了一些修改,例如减小了行距,增大了标题底部 margin,在大屏幕上两端对齐排版等。
然而并不是所有的样式都在这两个 CSS 中被指定,前面说 Tailwind CSS 最主要的功能是在 HTML 文件中快速指定样式,因此我们还可以在生成 HTML 文件的几个 js 文件中找到 Tailwind CSS 的痕迹。
再举个例子,BlogPost.js 我修改成了这样:
这个文件其实就是主页的显示效果,我想把简介的文字调暗一点,让文章标题文字更加突出,于是将最后一个 <p> 元素的 className 修改为 text-gray-700 和 dark:text-gray-400,查阅文档可知 text-color-### 代表字体颜色为指定的颜色,其中 gray-700 是 Tailwind CSS 默认调色盘中的一种灰色,而 dark: 前缀代表在系统深色模式下适用,所以代表在深色模式下,这里文字颜色使用 gray-400 颜色,比原来的更暗一些,可以实现我的效果。
如此类推,详细的对应关系可以在 Tailwind CSS 的 官方文档 中找到,文档有很方便的搜索功能,作为纯业余的我折腾体验也不错。另外网上还有 中文翻译版的文档 可供参考。
之后,可以再对一些元素进行进一步的修改,例如我给 footer 加上了 CC BY-NC-SA 的图标,并超链接到博客的版权页,拿掉了原来 Vercel 的徽章(放到了关于页里)。

深色模式下的 Notion 颜色

在默认的情况下,由于我的背景色设置就是全黑色,默认的调色盘显示 Notion 颜色(包括但不限于字体颜色、高亮颜色、背景色等)十分不明显,于是我手动吸取了 Notion 官方在深色模式下的各种色彩,并写到了 notion.css 中。
这里的颜色在 0 饱和度的各种深色背景下应该都可以使用(Notion 官方的深色背景色是 #191919,各位如果需要,在 notion.css 文件任意位置加入以下内容即可:
代码较长,折叠一下
notion image

Code Block 自定义:Prism.js

做完了以上全部,只剩一个地方没有满足我的强迫症。那就是代码块,不论 nobelium 的主题是明是暗,代码块始终是白底黑字,比较扎眼。查阅了 issue 之后,发现 #129 中 craigary 表示这目前是有意为之,并且提出了现在可以尝试 “switch to a dark prismjs CSS theme instead”。
虽然我并不知道他在说什么,但是我真的很喜欢深色模式,于是我就去 Google 了一下,发现 Prism.js 就是一个提供代码高亮的脚本。在 Prism.js 官网,发现官方就提供了深色主题的配色,于是我又去翻项目代码,发现是在 pages 文件夹下的 _app.js 文件中 Ln1 就导入了 Prism.js,我猜这里也是导入的官方的包,于是我在官网找到了另一套喜欢的深色主题色:Tomorrow Night,文件名是 prism-tomorrow.css。所以,我将导入的 prism.css 替换为了这个文件,重新部署后,果然代码高亮都变成深色的了。之后我又修改了 notion.css 为代码块制定了一个喜欢的背景色,看起来没有什么不妥。要说唯一的缺点就是在浅色模式下,代码块还是黑色的,但是我个人可以接受,因为白色背景下一块黑色应该不会比黑色背景下的一块白色扎眼。
notion image

OG image

折腾完以上的部分之后休息了一天,今天又心痒了看了看项目文件,发现在 blog.config.js 文件中的 ogImageGenerateURL 。这也是 nobelium 的一个 feature 之一,自带 Open Graph,但我折腾之后又发现了一些问题。
在原来的文件中,填写的是 craigary 自己部署的一个域名,在 Container.js 文件中 Ln39 被引用:
也就是说会将 OG image 指向一个域名,这个域名包含了被 UrlEncode 的文章标题和一些其他内容,可以推测应该也和 Gravatar 差不多,是可以通过 URL 直接提供 OG image 的。
于是我在 GitHub 找到了原来的仓库,也是 Vercel 的一个项目:Open Graph Image as a Service。简言之就是可以直接通过 URL 快速生成带有文字的图片,从而实现不用每张 OG image 都手动制作的效果。既可以直接访问网页在网页上制作,也可以直接使用特定的 URL 就会返回特定的图像。可以说和平常转换机场订阅节点的 API 很像了。
但是 craigary 提供的网址没有 nobelium 的 logo,只显示文字。猜测是指定的 logo URL 失效了吧。
notion image
访问 Vercel 官方的链接,可以显示并自定义 Logo,但是没有支持中文的字体:
这些方块都是中文……
这些方块都是中文……
于是自己折腾的机会又到了!
翻了翻 官方仓库 的 issue,发现 #108 提到韩语显示问题,果不其然是因为缺少字体。在这条下有 hoosan 的回复 详细说明了他对于同样的日文字体的解决方法。看起来对于中文也是可以适用的。于是我就打算动手自己部署一个,然后修改一下应该就可以解决问题了。
首先我们要自己部署一个原版的 vercel/og-image 项目,同样的还是首先 Fork 一下官方仓库,然后按照 README 的指引修改 vercel.json 文件中的内容,我直接删掉了架构、区域两行,然后调低了一点 memory(免费最多 1024MB),rewrite 保持不变,最后文件看起来是这样:
现在应该就可以到 Vercel 网站开始部署了,步骤和以前一样,还是从 GitHub 导入,框架选择其他,然后就可以让 Vercel 自动部署了。部署成功后可以打开网页看看,然后就可以开始进一步的修改了。
首先是添加字体文件。
Google Fonts 网站有提供各种 Noto 字体,那种由于字体缺失显示不出来的方框被大家叫做 tofu(豆腐),这套字体之所以叫 Noto,就是想要解决 tofu 问题,这里用这种字体感觉挺合适的。看到项目中其他字体文件都是 woff2 格式的,而 Google Fonts 网站本身不支持 woff2 格式的下载,所以我进行了一些搜索,发现了 google-webfonts-helper 这个网站,可以直接下载 woff2 格式的字体文件。
我选择下载了 Noto Sans SC medium 字体,勾选中文字符集和 500 字重,滚到页面底部可以直接下载所有字体文件。下载成功后解压,将 woff2 格式的文件保留备用。
notion image
为了方便,我将字体文件更名为了 noto-sans-sc-medium.woff2 ,并将该文件添加到自己项目的 api/_fonts 文件夹。
然后打开 api/_lib 文件夹下的 template.ts 文件,声明一个新的 const 读取刚刚的字体文件:
notion image
同一个文件向下翻,再添加如下一段 CSS 代码在下图位置:
notion image
接着再向下翻,在 heading class 的 CSS 中添加刚刚的字体:
notion image
保存结束以上的修改,再将以上的修改推到 GitHub,Vercel 应该又会自动开始部署了,等到部署完成再打开网页,虽然外观没有变化,输入中文试试吧。
notion image
大功告成,又有图片又有中文支持的自动生成 OG image 网站就完成了。接下来进行一些小调整,使用暗色背景,增加了一个 nobelium 图标,字体大小增大了一点点,大概看起来就是这样:
notion image
但是只在前端操作不是我们的目标,我们做一个可以自动根据文章标题生成对应 OG image 的链接。所以我们点击右侧的图片复制地址,得到了这样的一个 URL:
可以看到,**Hello**%20World%20%E4%B8%AD%E6%96%87%E6%B5%8B%E8%AF%95 这一段应该就是我们的标题经过 UrlEncode 的文本,.png 是选定的文件类型,而 theme=dark md=1 fontSize=125px 等内容就是我们其他的自定义设定了。因此我们现在要做的就是在之前提到的 blog.config.js 和 Container.js 文件中修改使用我们自己的域名和设置就好。
首先将 blog.config.js 文件中的 ogImageGenerateURL 修改为自己部署的 og-image 的域名(Vercel 会自动分配的),然后再到 Container.js 文件中,找到 <meta> 标签下 property 为 og:image 的内容,将包括 .png?theme= 在内后面的内容选中,替换为刚才的那个 URL 中对应的内容即可。下面的 Twitter Card Image 设置也可以进行一样的修改。我的设置如下:
可见这里的内容就是先取刚才的 blog.config.js 中的 ogImageGenerateURL 内容,加上斜杠,再加上 UrlEncode 后的文章标题,再加上一串自己代表特定样式的字符串,拼成了一整个动态生成 OG image 的 URL。
保存修改,再推到 GitHub,等待 Vercel 部署完成,再打开博客,使用检视工具就可以看到 OG image 链接了。再使用 Telegram 和 Twitter 测试一下,完美符合预期!
Ta-da!
Ta-da!

优势

打开 nobelium 的网页,第一个感觉就是快。比起以前搭建在 GitHub Page 的静态博客,这可快多了,基本看不到加载,点击一个链接后立刻就会有内容显示。
notion image
作为对比,这里也展示一下原来的 Gridea 静态博客的 Lighthouse 分数:
notion image
其次,使用 Notion 作为 CMS 也比以往 Gridea 中编辑 Markdown 文件更加方便。以往写一篇博客虽然也可以先在别的地方写,然后在移动到 Gridea 中,但是最后一步的发布还是要在电脑上操作。而且如果博文有图片,还要解决图片问题,要么使用图床,要么就要一个个图片文件导入到 Gridea 中。并且我的 Gridea 可能是因为网络问题,长期无法在客户端 push 成功,我每次都要在客户端点击同步,然后退出,检查 output 文件夹中的静态页面文件是否更新成功,最后再用 Git 手动 Push 一下。比起在 Notion 中编辑完成,把标签直接改成 Published 就能实现发布,实在称不上方便。
notion image
但 nobelium 的方案也称不上完美,还是有几个地方让我怀念 Gridea 的 Markdown 文件。
首先是灵活性收到了一定程度上的限制。Markdown 文件可以直接向上(下?)兼容 HTML,所以有时候一些个别的、需要自定义的元素(比如一些 badge 或者居中的文字什么的)可以直接用 HTML 写出来,但是在 nobelium 下,博文的内容其实就是 Notion 页面的内容,而且也并非支持 Notion 中全部的 block 种类例如新推出的简单表格、可折叠的标题就还没有支持,文字也无法居中等。可以说对于简单的图文博客,偶尔插个视频那是完全够用,但是如果对于控制博客页面有更高的要求,nobelium 使用 Notion 的方法可能比不上直接使用 Markdown 灵活。
左侧下方为简单表格,在 nobelium 中暂时不支持  新版本支持了!🎉
左侧下方为简单表格,在 nobelium 中暂时不支持 新版本支持了!🎉
此外,nobelium 还要从 Notion 中取内容,所以一般会选择公开一个 Notion database,如果选择真的使用 Notion 当作博客的内容管理系统(使用标签区分发布和草稿的内容),那么公开的 database 可能会让一些没有准备好发布的内容公布在互联网上。我个人是完全没有这方面的顾虑,因为我很少直接在 Notion 中写作。nobelium 还提供了一种使用 NOTION_ACCESS_TOKEN 来获取内容的方法,可以不用共享 nobelium 的 Notion database,看起来就是携带 Token 访问 Notion 内容,一个 Token 有效期是 180 天,对于我这种金鱼脑,我自然不会选用这种方法。根据作者 craigary 的 roadmap,nobelium 未来应该会支持从 Notion 官方的 API 获取内容,最近 Notion API 也正式结束 beta 阶段了,对 craigary 更新表示期待!
最后,我原来的 Gridea 站点已经断断续续打磨了很久,很多细节已经符合我的喜好,这可能算是一次性迁移到 nobelium 的「沉没成本」吧,我无法舍弃原来的 Wonder Space 那快两年的修补、自己加的一堆的样式、Telegram 即时预览模板、OG 属性、还有以前网友的评论。

域名

折腾完上面的东西,已经过去两天了,但是当时我完全没有停下的意思。有一天看网邻罗二德的 博客,发现他原来的 GitHub Page 有了自己的域名,我就想起来我一直想要有个域名。那天其实已经是凌晨两三点了,但我还是说干就干开始搜索有关购买域名的信息。
我以前看的购买域名之类的内容多是在 GoDaddy 之类的网站购买,需要外币支付手段,当时看到我就被劝退了。那天搜索之后发现其实国内各种云就可以直接购买域名,于是我就在阿里云的万网搜索了一下。不看不知道,我之前一直以为域名一年至少是几顿饭的支出,但我搜了一下我想要的 L3ON 前缀,发现 l3on.site 这个看起来还挺酷的域名一年竟然只要 6 元……我一边后悔怎么没早点动手,一边下单了一年。
在万网购买只需要支付宝账号就可以登录,也可以直接用支付宝绑定的手机号做实名认证。我接受了这种隐私换来的方便(反正我博客内容还是挺阳光的吧),上传身份信息,不到半个小时就搞定了实名认证,当时已经凌晨四点多了,系统提示实名认证可能要 24-48 小时,我就想着睡觉了,过几天再折腾。
结果第二天醒来就看到了收件箱的邮件,当天早上 6:50 我就收到了实名认证通过的消息,希望是机器识别的,不然阿里员工上班时间有点过早了。
Vercel 的域名绑定其实很简单,只需要进入项目的设置,填写自己的域名,然后再在域名的 DNS 设置中加入一条 CNAME 记录就可以了,我出于折腾的本性,还把域名的 DNS 改成了 Cloudflare 的,添加了 CNAME 后,不到五分钟 blog.l3on.site 域名就生效了。记得当时我就对着屏幕,看着浏览器地址栏中这一串在浩瀚互联网世界中代表我的角落的一串字符,一次次刷新页面,觉得一点一点变开心。
原来的 GitHub Page 也可以自定义域名,和 Vercel 一样简单,只需要在仓库的根目录新建一个 CNAME 文件,内容为自己的域名,我选了 ws.l3on.site ,或者直接在 Gridea 的远程设置中填写自己的域名,再把变动 push 到远端就可以了。之后再在 Cloudflare 增加一条 CNAME 记录,指向原来的 github.io 域名即可。现在,我在互联网有两个差不多的角落了。

总结

所以这两个博客我该留一个放弃一个吗,我暂时觉得我可以一个都不放弃。Gridea 更像一个完整的博客网站,自定义程度更高,但是对应的管理也会相对复杂;nobelium 强大而快捷,让我体验了一把一些相对先进的技术,也给我带来了几个晚上学到新东西的快乐。所以我觉得没必要要求自己二选一。因为博客对于我来说,不是我的工作也不是我的负担,更多是我的玩具,连小孩子都不会拒绝两个玩具,我当然两个都要。
但是我也不想只专注于这些东西而忘记了内容。技术对我有一种莫名的吸引力,总想让我去尝试新的东西,但是真的遇到难对付的问题时,我又往往懒于进行深度系统的学习,可能这也是我为什么长期三脚猫功夫的原因吧。这次整理博客的时候又看了一下我的第一篇博文,我想起我的初心还是想有个自己能写下自己所学所想的东西的地方,之前的两篇随感类的博客比较符合想象中的博客的样子,就是和自己、也和一群看不见的读者分享一些自己最想说的话。
所以前几天折腾完博客,筋疲力尽,开心中又夹杂着一点点负罪感,我怕我又是在玩物丧志,正事不做只知道瞎折腾,虽然有做了很多事情的成就感,但是又觉得如果我什么都不记录下来,就算我当时以为我会了的东西我也会慢慢遗忘,然后这些花费我大量时间的事情似乎没有意义。所以我很庆幸我今天一时冲动就开始打字了,从上午到深夜,一口气写了一万多字,我也被自己惊讶到。未来的一段时间,我可能要从爱好中抽身,转移更多的精力到生活中一些现实的问题上了,所以这篇长文也有点像收心前最后的狂欢吧。
最后的最后,如果你看到了这里,谢谢你。如果文章对你有那么一点点的信息增量甚至是帮助,那是我的荣幸,不论你是在我的哪个角落看到这篇文章,欢迎留言交流,也欢迎你到我另一个角落玩。

©️ L3ON 2020 - 2024