基于 Astro 的博客初体验
现如今想拥有一个独立博客已经是非常简单的事了,然而想要把博客长期维护下去却依旧是有些挑战性的。在上一个自建的 BearBlog 博客夭折后,我原本没这么快就打算重启的,然而前两天碰巧让我看到在 Dynadot 注册 .NG 域名只需 CNY 66.20,我比之前在趣域上注册的时候还要便宜,而且自然无须实名,重新开博的理由这不就有了。
初上手
在调研博客框架的时候,我又注意到了已经眼熟但还从未用过的 Astro,之前我对它的印象更偏向于 Next 那样全能的前端框架,所以总觉得要是直接拿来做博客的话,会不会有点太复杂了。然而架不住推荐的人多,那正好借这个机会体验一下。
打开官方的博客主题目录,看起来和其他传统静态博客生成器的目录也没什么差别,于是我随便下载了一些主题试用,果然用法还是有点不同的。这里的主题更像是 Starter,也就是一个包含有 Astro 依赖的完整前端项目,所以在本地调试的时候必须依托 Node.js 的运行环境,无法直接提供二进制的 CLI 给用户。
不过对于普通用户而言,通常情况下只需关注主题中预留的配置文件和内容目录可以了,这样倒是和传统的静态博客生成器区别不大。只不过想要对主题进行修改的话,就需要更多知识储备了,毕竟 Astro 的语法比传统的模板引擎要复杂,当然自由度也大得多。
顺便容我吐槽一句,要把 Markdown 文档放在 src/ 目录下总感觉有点奇怪,当然这种行为肯定也可以是自定义的,只不过这是目前比较通行的约定。
主题选择
这应该是每次开博最令人纠结的问题,没有之一。我的选择标准这些年倒是比较稳定,主要青睐单栏的简洁风格主题,这次主要尝试了以下几个,在此附上简评。
- MultiTerm: 提供丰富的配色和 Markdown 扩展语法,默认嵌入等宽字体
- Chiri: 类似 BearBlog 的极简设计,不错的细节打磨
- Cassidy's blog template: 特色的彩色超链接下划线,默认嵌入等宽字体
- AstroPaper: 较为知名的博客主题,功能丰富,默认使用等宽字体
如你所见,我最后选择了 Chiri 这款 7 月份发布的主题,它也是上述几个主题里面最简洁的一个,修改起来也相对容易。
--
字体选择
其实从上面就能看出来,我自己是比较偏好使用等宽的西文作为默认字体的,毕竟中文本身就是等宽的,搭配等宽的西文也不会让人觉得特别违和。当然 Chiri 默认搭配的 Inter 也很美观,而且字体的特性非常丰富。
上述主题的嵌入字体包括 JetBrains Mono 和 iA Writer Mono 这两个等宽字体,说实话我也都挺喜欢的,只不过它们和中文字符的宽度并非是严格的 2:1,而想要做到这一点就需要去找专门的字体了,一般只有中日韩等国的字体设计师会才会考虑这一点。
对我而言,在符合要求的字体中,最有名的当属更纱黑体的 Mono 版本了,完全可以做到开箱即用。另外,其内置的西文字体为 Iosevka,也是非常不错的,不仅有多个风格的变体可选,而且很容易和其他的中文字体搭配成 2:1,比如我经常会将其和 HarmonyOS Sans 一起用在自己的项目里。只不过同一款字体用多了总会审美疲劳,所以这次在纠结之后我还是决定要换个口味。
在找字体的过程中,我发现微软的 Cascadia Code 去年推出了一个测试版,名为 Next,提供对中文和日文的试验性支持,而且是可变字重的。我试用了一下感觉还不错,考虑到之前西文版一直都是我非常喜欢的等宽字体之一,所以最终敲定选它作为博客正文的字体。虽然测试版还有些小毛病,但实际影响不大,只是个人认为这款字体的默认字重偏细,需要适当加粗。
对了,对于内嵌的绘文字我也一并采用了微软的 Fluent Emoji Color 字体。🐲
主题微调
为了满足自己的喜好,对主题进行小幅度的调整也是必要的。这里的内容比较琐碎,我挑选了一些放在下面。
固定链接格式: 此概念是来自传统博客程序的,对应到这边主要就是 pages/ 目录下文章页面模板的存放路径,同时渲染文章列表的地方要和上述路径对应得上才行,注意别忘了还有 RSS。
以 Chiri 主题为例,需要修改的地方有 1 和 2 两处。
OpenGraph 预览图字体: 大部分主题都会提供动态生成预览图的功能,但要注意生成图片时使用的字体是要单独指定的,对于没有专门做中文支持的主题,需要手动去将字体改成支持中文的字体。另外 astro-og-canvas 似乎是不支持可变字重字体的,建议用 fonttools 将需要的字重单独提取出来再用。
以 Chiri 主题为例,在此处修改即可。
SmartyPants 插件: Astro 在渲染 Markdown 时会自动把正文中的直引号变成弯引号,也就是 Word 中所谓的智能引号。这个效果我一开始误以为是字体通过某个内置的 OpenType 特性实现的,然而调试了一番都没有效果,实际上 Cascadia 系列本来也就没有这种特性,更别说我用的还是 Next 早期不完整的测试版了。
随后我突然发觉,原来 HTML 输出中的引号就已经被自动替换掉了,于是我又试图从主题这边入手,看能否修改对 Markdown 渲染引擎的调用,结果发现一般情况下主题中并不需要直接进行此类调用,Astro 会自动处理好相关的工作。
最后我才意识到,Astro 的 Markdown 渲染是通过 Remark 实现的,自然也能支持其丰富的插件系统。其默认启用了两个插件,其中之一为 SmartyPants,这才是根本原因所在,因此只需在配置里禁用该插件即可。
新窗口打开外部链接: 由于这不是标准的 Markdown 特性,对于那些不支持自定义的渲染引擎来说就不太容易直接去修改了,然而有了解决上一个问题的经验,这时只要去找有没有相关的 Remark 插件就可以了,于是很容易就能搜到 rehype-external-links,想必这也是一个比较通用的需求。
注意该插件默认是不会对链接进行任何修改的,所以需要明确地传入参数。
// 文件: astro.config.ts
// 安装依赖: pnpm install rehype-external-links
import { defineConfig } from 'astro/config'
import rehypeExternalLinks from 'rehype-external-links'
export default defineConfig({
/* 其他配置略 */
markdown: {
/* 其他插件略 */
rehypePlugins: [[rehypeExternalLinks, {'target': '_blank'}]],
},
})
CSP 错误修复: 目前 Chiri 主题的 CSP 设置似乎有点问题,当访客第一次从首页进入文章页面时,浏览器会产生如下的报错。
Refused to load the script 'data
/javascript,' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' https:". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
说实话,这里执行的脚本着实让我有点迷惑,明明什么实际的内容都没有,到底是为何要执行这种代码呢。于是我搜索了一下,原来这应该是个 Trick,具体调用的位置在这里。
于是我尝试在 script-src 末尾加入 data:,具体位置在这里,最终问题得以解决。由于这个问题在本地调试的时候似乎不会被触发,所以一开始我也完全没注意到。
部署平台
Astro 支持生成纯静态的站点,因此可直接部署到 GitHub Pages。只是 Chiri 主题中有一个生成链接预览卡片的功能用到了服务端的按需渲染,所以就只能选择其他部署平台了,当然这个功能本身是可选的。之所以需要这样通过服务器进行代理请求,主要还是为了解决跨域的问题。
总之免费的选择还是有很多的,因为之前还没有用过 Netlify,所以这次就选它了。试用了一下,和 Vercel 的体验类似,该有的都有,挺好。