我的博客是怎么搭起来的·续:从 v1.4 到 v3.2,24 个版本、73 次提交
上一篇搭建教程发布后,博客三天内迭代了 24 个版本、73 次提交:视频嵌入、文章页评论、图志广告牌、全站词云、View Transitions 动画、四套视觉主题与前端定制后台——这篇续文讲清楚原文章之后发生了什么。
我的博客是怎么搭起来的·续:从 v1.4 到 v3.2,24 个版本、73 次提交
上一篇《我的博客是怎么搭起来的:技术栈总结与从零搭建教程》发布时,这套博客停在 v1.3.2。文章写完后我没停下来,三天之内版本号从 v1.4.0 一路刷到 v3.2.1——24 个版本、73 次提交,平均两小时一个版本。今天这篇续文,就是把「原文章之后发生了什么」一次性讲清楚。
先给一张时间线总览,再按主题拆开讲:
| 版本 | 日期 | 一句话 |
|---|---|---|
| v1.4.0 | 08-01 | 文章可内嵌视频(B站 / YouTube / 通用 iframe) |
| v1.5.0 | 08-02 | 图片全部迁到独立图床仓库 + jsDelivr |
| v1.6.0 | 08-02 | 文章页底部新增评论(Waline 同后端) |
| v1.7.x | 08-02 | 图志页大改:文章图集视图、分页、独立收藏广告牌 |
| v2.0.0-macOS | 08-02 | macOS 适配,双端开箱即用 |
| v2.1.0 | 08-02 | 管理面板新增 Git 同步 |
| v2.2.x | 08-02 | 广告牌三轮迭代:焦点轮播 → 全量轮播 → 线性轨道 |
| v2.3.x | 08-02 | 新增词云:全站关键词索引 + 单篇关键词 |
| v3.0.x | 08-02 / 08-03 | 全站 View Transitions 衔接动画(+ 两个硬核修复) |
| v3.1.0 | 08-03 | 双主题固定文案适配 + 极简导航修复 |
| v3.2.x | 08-03 | Liquid Glass 主题、前端定制后台、双版式文章列表 |
内容能力:视频与评论
v1.4.0:文章里直接嵌视频
以前文章只能放图和文字,想分享 B 站视频只能丢链接。v1.4.0 之后,Markdown 正文里直接写 <iframe> 就能嵌入播放器——管理面板编辑器还多了个「▶ 视频」按钮,粘贴 B 站链接(支持 ?p=N 分P、纯 BV 号)、YouTube 链接(watch / youtu.be / shorts / live)或任意网站的 iframe 嵌入代码,一键生成响应式代码插入光标处:
<!-- 粘贴 B 站链接后自动生成 -->
<iframe src="https://player.bilibili.com/player.html?bvid=BVxxxx" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
页面端配了 16:9 自适应样式(宽 100%、高度自动),移动端不溢出;YouTube 统一走 youtube-nocookie.com 隐私域名。编辑器实时预览也同步支持 iframe 渲染——只提取闭合完整的 iframe、丢弃 on* 事件属性、src 限 http(s) 协议,围栏代码块里的 <iframe> 不会被误提取。我实际用的东西永远是「少依赖、安全兜底」这套思路,连一个预览渲染器都要考虑注入面。
v1.6.0:文章页底部也能评论了
v1.6.0 在文章页底部新增评论区(FINIS 之后),与留言页共用同一个 Waline 后端,按文章 URL 隔离;版式沿用 B 站评论区风格——字母头像哈希取色、昵称、IP 属地、相对时间、楼层号。
一个关键决策是地区降级:请求带 8 秒超时,加载或提交评论失败一律显示「当前地区暂不支持评论」提示,不影响正文阅读;导出 PDF 时评论区自动隐藏。不迁就大陆网络,但也不让评论系统拖垮阅读体验——这比评论区本身更重要。
图志页的进化:从双档案到「画廊 + 广告牌」
原文里图志页还是「随文图像 + 独立收藏」两个静态面板,v1.7.x 到 v2.2.x 把它迭代成了全站交互最复杂的页面:
- v1.7.0 文章图集视图:随文图像新增「时间线 / 文章图集」双视图,图集是朋友圈式版式——按文章分组,每组大标题 + 日期/张数 + 阅览全文链接,下方一排小缩略图;两个视图都加了每页 9 张的分页,FOLIO 编号跨页连续。
- v1.7.2 独立收藏广告牌:面板顶部多了一条「广告牌」——焦点轮播,当前图居中放大 1.2 倍,两侧图缩小到 0.82 倍并弱化,3.8 秒自动切换,点击两侧图直接切换、点击焦点图打开大图查看器。
- v2.2.0 全量轮播 + 分页:广告牌不再随机抽 5 张,而是 Fisher–Yates 洗牌后全部独立收藏参与轮播;独立收藏面板也加了每页 9 张的翻页器。
- v2.2.1 → v2.2.3 三轮布局修复:宽图在候播区与相邻图重叠 → 步长同时满足「候播图互不重叠」和「焦点与候播不重叠」两类约束;间距又改成逐对自适应(相邻中心距 = 各自半宽之和 + 固定间距,实测所有相邻对空隙恒 18px);最后取消环形布局改线性轨道,末张播完瞬移切回首张。
这些修复背后是同一套方法:headless Chrome 构造宽窄交替图片(900px/300px)实测布局,逐像素验证不重叠。视觉问题最难的就是「说不清、测不准」,把布局约束写成可复现的断言,迭代效率完全不一样。

v2.3.x:全站词云
v2.3.0 新增了词云:目录页新增「INDEX VERBORUM / 关键词索引」(全站正文词频统计、Canvas 渲染 80 个词,点击跳 Google 站内搜索,hover 显示词频),文章页左侧边栏是单篇词云(≤24 词):

实现上最值得说的是中文分词零依赖——用 Node 内置的 Intl.Segmenter 分词,加内置停用词表;正文先剥离代码块、行内代码、链接和 URL,否则英文 token 会淹没中文主题词。词频做对数缩放映射字号,标题加权 2 次。渲染用 vendored 的 wordcloud2.js(MIT),UMD 导出改成 globalThis + ESM 默认导出以适配 Vite 打包。
发布后踩了两个坑,都很有代表性:
- 词云一片纯白——
color传数组不被 wordcloud2.js 支持(浏览器忽略无效 fillStyle),改为传函数每个词从主题色板随机取色;另外它默认backgroundColor: '#fff'会把 canvas 整块涂白,暗色主题下浅色词全看不见,改成transparent露出主题底色。 - 布局填不满——v2.3.2 改用
ResizeObserver+ 迭代填满:绘制后统计被丢弃的词,放不下就整体缩小字号重试,全部放下后再逐档放大直到刚好放不下回退一档,实测像素占用提升约 88%。
顺带一提,v2.3.3 还修了一个隐蔽 bug:同日发表的随文图片没继承文章的 dayIndex,导致「从新至旧」重排后同一天内的顺序完全颠倒——现在随文图片继承 dayIndex,画廊默认视图也改成了「文章图集」。
工程化:双平台 + 管理面板同步
v2.0.0-macOS
博客原本是 Windows 工作流(.bat 启动器、npm.cmd 硬编码),v2.0.0 补齐 macOS:新增双击 .command 启动器,pre-commit 钩子里的 npm.cmd run build 改成跨平台的 npm run build。现在两端的日常使用完全一致:写 → 管理面板上传图片 → push → Actions 自动部署。
v2.1.0:管理面板会自己同步了
多设备写作最容易出「两台电脑打架」的问题。管理面板新增 Git 同步:启动时自动 git fetch 并与远端比对,本地落后就快进合并(不产生 merge 提交);侧边栏还多了「⇩ 拉取」按钮随时手动同步。安全护栏是关键——仅当「远端领先、本地无未推送提交、工作区干净」时才自动拉取,有未推送内容就跳过并打印原因,绝不覆盖本地工作。
v3.0.x:全站动画,以及两个血泪坑
View Transitions
v3.0.0 给全站接入了 Astro 的 View Transitions(ClientRouter):页面导航时旧页 140ms 淡出、新页 280ms 淡入上移;明暗主题切换交叉淡化;画廊 tab / 视图切换有「轻盈升起」动画;排序重排用 FLIP 动画让卡片平滑位移到新位置;查看器打开淡入微升。所有动画都在 prefers-reduced-motion 保护内,系统开启减弱动态时自动禁用。静态站也能有流畅的原生级动效,而且是渐进增强——不支持 View Transitions 的浏览器自动回落。
v3.0.1:View Transitions 的脚本陷阱
升级后立刻翻车:通过页面间切换进入的任何页面,昼夜切换按钮全部失效,刷新后才恢复。根因有两层:
- Astro
ClientRouter有脚本去重机制——全站同文本的内联脚本只在首次执行,VT 导航后被跳过,新 DOM 上的按钮没有监听器;同时 swap 会移除<html>上的data-theme属性,主题即丢失。 - 修复时踩到第二个坑:给打包脚本加
data-astro-rerun会隐式内联(Astro 文档:给<script>加任何属性即隐式is:inline),TS 泛型和import直接泄漏进浏览器语法报错。
最终方案:主题脚本改为 is:inline data-astro-rerun 并用 IIFE 包裹(内联脚本重复执行时顶层 const 会抛重复声明,IIFE 规避);含 import/TS 的页面脚本改用 astro:page-load 事件驱动初始化,每次导航重新绑定,initOrderToggle 加 WeakSet 幂等保护。
v3.0.2:TDZ 崩溃
紧接着又修了一个:图志页初始化直接抛 ReferenceError: Cannot access 'billboardTimer' before initialization——selectGalleryTab 的初始调用位于 let billboardTimer 声明之前,调用链 selectGalleryTab → pauseBillboard → 访问 billboardTimer 触发 TDZ,整个脚本初始化中断。这个 bug 自 v2.2.0 引入广告牌时就存在,只是直到 v3.0.0 加了动画、测试范围扩大才暴露。修复很简单(初始调用移到脚本末尾),但它说明**「能跑」和「初始化顺序正确」是两回事**,TDZ 这类错误在重构里很容易被忽视。
v3.2.x:主题革命与前端定制
四套视觉主题
原文时代还只有「私人档案」一套视觉。v3.2.0 之后是四套主题,且分成两组风格:
- 静澈(still)/ 流形(fluid)——v3.2.0 新增的 Liquid Glass 风格:玻璃表面、受控模糊、清晰边界,兼顾材质感与正文可读性;标题字体提供 Noto Serif / Noto Sans 选择;
- 留白(minimal)/ 行迹(trace)——保留的经典主题,延续卷册、入藏、编目叙事。
主题选择在关于页,独立于昼夜模式,跨页面持久化。v3.1.0 先做了一层铺垫:新增 ThemeCopy 组件,把全站固定界面文案按主题区分——留白用直接、现代的中文表达,行迹延续「卷册 / 入藏 / 编目」的档案叙事,覆盖导航、首页、目录、词云、留言、评论和 404 页。
前端定制后台
比主题更重要的变化是把设计参数变成了数据:管理面板新增「前端定制」标签页,可以调整默认主题、站点名称与副标题、首页文案与主按钮、两套主题的背景图与焦点、字体、主题色、玻璃不透明度、遮罩、模糊与卡片圆角:

配置存到 src/data/frontend.json,纳入后台推送流程——改完点「⬆ 推送」直接上线,不需要碰代码。这延续了博客的核心哲学:内容即文件、构建期干重活。现在「设计」也成了文件。
同一版还加了文章封面上传(首页与文章页共用卡片 / 横栏双版式,横栏优先用封面、其次用正文第一张图),五个主页面内容宽度统一限制为视口 80%,以及 VT 导航下主题持久化修复(before-swap / after-swap / page-load 三阶段同步已保存的主题)。
v3.2.1:列表细节
最后一版是细节打磨:文章条目序号改为纯数字 01 / 02 / 03…;标题区高度固定为两行,标题过长时按 0.25px 步进微调字号直至完整展示,不再省略号截断——极端超长标题缩到下限(基准 55%、不低于 12px)后由固定行数截断兜底。

更新后的技术栈
对比原文的表格,两年(好吧,两天)后变化如下:
| 层 | 原文 | 现在 |
|---|---|---|
| 静态站点生成 | Astro 7(static) | 不变,新增 View Transitions 路由动画 |
| 内容管理 | Markdown + Content Collections | 不变(新增 dayIndex 同日排序字段) |
| 写作工具 | Obsidian + 管理面板 | 不变 |
| 管理面板 | 文章 CRUD、传图、推送 | + 视频插入、前端定制、Git 同步(启动自动比对 + 手动拉取)、关于页编辑 |
| 图片托管 | 独立图床 + jsDelivr | 不变(构建期 sharp 插件已移除,只有管理面板上传时转码) |
| 部署 | Actions + Pages | 不变 |
| 评论 | 留言页(Waline) | + 文章页评论区(同一后端,地区不可达降级) |
| 访问统计 | 不蒜子 | 不变 |
| 画廊 | 随文图像 + 独立收藏 | + 广告牌轮播、文章图集视图、分页、缩放拖拽查看器 |
| 词云 | — | 新增:全站关键词索引 + 单篇关键词 |
| 视觉 | 私人档案单主题 | 四套主题(静澈 / 流形 / 留白 / 行迹)+ 前端定制后台 |
结语
原文总结的哲学三条——内容即文件、构建期干完所有重活、少依赖——一条都没变,反而被验证得更彻底:词云分词用 Node 内置 API 而非分词库,评论降级不引第三方兜底服务,连管理面板的新功能(Git 同步、前端定制)都还是零框架手写。
这 24 个版本带来的新体会也有三条:
- 视觉 bug 要可复现地测:广告牌布局、词云像素占用、VT 脚本重绑定,全部用 headless Chrome 写成断言验证,才能两天迭代 24 个版本不翻车;
- 动效是渐进增强:View Transitions、FLIP、
prefers-reduced-motion——支持的浏览器享受流畅衔接,不支持的也不影响功能; - 把设计变成数据:前端定制后台让「改博客」从改代码变成填表单,这是静态站最被低估的生产力提升。
如果你照原文搭了自己的博客,这篇里最有复用价值的是三个点:astro:page-load + data-astro-rerun 的 VT 脚本模式(v3.0.1 踩坑总结)、headless 验证视觉布局的工作流(v2.2.x)、以及「设计参数进 JSON」的前端定制思路(v3.2.0)。