一个从零实现的个人博客
起因
我也有经常写笔记的习惯,经常使用Obsidian,但写法、内容几乎都是面向我自己。我也有想过把内容分享出来,但在之前想完整复刻Obsidian的关系图谱很困难,一拖再拖就没有实现。
年后,在投递的这段时间里,我难免焦虑,不写代码快有两个月了,对常用的东西也会手生,所以我尝试开发了ai-chat,整个过程很流畅。在出租屋里写代码的时候我也不再焦虑,那干脆就再开发一个博客项目吧
这大概就是我为什么没有直接使用一个博客框架的原因,博客一共分为三个部分,技术文章、我的思考、我的日常
选型
我并不是像正常的产品需求一样进行拆分,我没有原型,只是将需求的内容一点一点补充
- 我的博客部署在哪里
- 如何将md文档直接渲染成html,我如果想在md中写一些样式怎么实现
- 如何在文档提交后,就立即更新
- 是否需要制定版本与回滚、访问统计、性能指标
是否需要ESLint、CommitLint肯定需要
部署
最初我的想法是托管在GitHub,为此我甚至准备好了Actions;但后来我切换到了Vercel Github Pages仅支持静态HTML,如果以后想添加更丰富的内容就很困难 Vercel开箱即用,包含完整的CI/CD、数据收集、日志、性能指标(回滚需要Pro),也支持SSR、Serverless
渲染
简单来说就是md的渲染,@nuxt/content,毋庸置疑
那如果想在md中写写一些样式呢,可以直接写Vue组件,也可以使用 MDCMarkdown Components
CI/CD
CI/CD依靠Vercel即可
遇到过的问题
文章的名称是纯中文字符时路由出错
像往常一样推送后发现很多文章都显示同样内容,并且路由都是父级路由,再发现它们都是纯中文命名
Nuxt Content 用 slugify 生成 path,默认会去掉非 ASCII 字符,导致纯中文文件名被 slug 成空串,多个文件都变成 /engineering 或 /thinking,产生冲突。数据库显示 stem 仍正确,但 path 错误。正在向 nuxt.config.ts 添加 content:file:afterParse 钩子,根据 stem 恢复正确的 path。
所以每篇文章现在都添加了属性path作为它们的路由
LCP异常
FCP、TTFB
以下数据均为我在同一设备访问页面产生


当前 FCP 偏高的本质原因不是页面慢,而是卡在 1.8s 的阈值附近。从数据上看,FCP 和 LCP 完全重合,说明页面没有提前渲染任何可见内容,而是依赖主内容一次性渲染。同时 TTFB 达到 1s,也显著推迟了首屏时间。
优先降低 TTFB,再让 FCP 和 LCP 解耦,从而把 FCP 降低至 1.8s 以内。
解决方案:
TTFB指标表现差通常因为SSR 渲染、API(服务器处理请求并生成响应的时间)、CDN命中率、网络延迟
/不进行SSR,/进行预渲染 ——/blog/**已预渲染,但首页/仍为 SSR,每次请求都会在 Vercel 上执行 serverless +queryCollection- 降低首屏CSS —— 项目将 KaTeX 全局 CSS 在
app.vue中加载,可改移到仅文章页
效果如下:


因为vercel当前统计数据是统计值,固有所偏差

字体问题
我本地使用霞鹜文楷,我希望我的博客也是霞鹜文楷
有两种方案:
- 本地提供woff2,构建时把字体打进产物,预渲染出的 HTML 里只引用 CSS,但这样会导致资源的体积变大(尽管去采用专门提供给Web的集合,如霞鹜文楷 网络字体仓库,体积仍然不小)
- 引用CDN,这仍会导致需要加载的资源体积变大,并且要考虑公共CDN的稳定性,且会丧失Vercel的优势
目前没有较好的思路,或许可以采用性能指标来衡量哪种效果更好,又或许是我想得不对,等待后续验证
MDC中使用原子类不生效问题
比如
::blur-reveal{class="pt-8" :duration="0.75"}
一些填充内容
::
因为UnoCSS不会扫描未被import到构建流程的文件,所以md文章中样式不会被扫描
在UnoCSS的配置里添加即可,目的是告诉UnoCSS去扫描md文件中的原子类,源码
content: {
filesystem: ['content/**/*.md'],
},