AI 正在绞尽脑汁想思路 ING···
AI 摘要
DeepSeek & Kimi

§ 背景

博客此前使用 Valine(LeanCloud 后端 + MiniValine UI)作为评论系统。LeanCloud 预计 2027 年 1 月停止服务,为获得更可控的评论数据、支持邮件通知,以及更现代化的评论体验,决定迁移到自部署的 Twikoo[1][2][3](部署在 CloudFlare,反代到 white-album.top/twikoo/backend)。

§ 迁移架构

博客用户 → 前端 Twikoo 客户端 (twikoo.nocss.js @ 1.7.7) → 后端 API (https://white-album.top/twikoo/backend) → Serverless (CloudFlare Workers) + 数据库 (Cloudflare D1) + 云存储 (Cloudflare R2)

§ 修改的文件与目录

§ 一、博客仓库(llxlr/blog

#文件/目录改动内容
1source/twikoo/Twikoo 独立测试页面,用于调试评论组件,不参与全局评论渲染
2source/twikoo/index.md引入 Twikoo CDN,初始化 twikoo.init(),envId 指向 white-album.top/twikoo/backend
3scripts/tags/test.js早期测试:通过 hexo.extend.injector.register('head_end', ...) 注入 Twikoo CDN,现已弃用(主题已内置 vendor 加载)
4scripts/injectors/global.js全局注入器,未做修改——Twikoo 的脚本加载完全由主题的 vendorJs('twikoo', ...) 处理
5_config.shoka.yml添加 twikoo 配置段,设置 enable: true / mode: vercel / envId;同时更新了 Valine 的 AppId/Key

§ 二、主题仓库(llxlr/hexo-theme-shoka,子模块)

主题层面经历了 5 次迭代,最终改动了以下文件目录:

shoka
tree .
themes/shoka/
├── _config.yml                                  ─ 主题默认配置 + vendor CDN
├── layout/
│   ├── _macro/
│   │   ├── comment.njk                          ─ 评论区域模板
│   │   └── widgets.njk                          ─ 侧边栏"最近评论"
│   └── _partials/
│       ├── layout.njk                           ─ 全局 LOCAL 对象注入
│       └── post/footer.njk                      ─ 文章底部访问量统计
├── scripts/generaters/script.js                 ─ 全局 CONFIG 对象生成
└── source/
    ├── js/_app/
    │   ├── pjax.js                              ─ Pjax 刷新 + Twikoo 核心初始化
    │   └── page.js                              ─ 评论区懒加载
    └── css/
        ├── comment.styl                         ─ 评论 CSS 入口
        └── _common/components/third-party/
            └── twikoo.styl                      ─ Twikoo 完整样式表 (2063)

§ 主题迭代时间线

§ 第一阶段:添加 Twikoo 支持(2025-08-31)

commit 4b80e2b — 8 文件改动,+117/-20

  • _config.yml:新增 twikoo 配置段(enable: false / mode: vercel / envId: ""),vendors.js 中加入 twikoo: npm/twikoo@1.6.44/dist/twikoo.min.js
  • comment.njk:根据 theme.twikoo.enable 条件渲染——启用时输出 <div id="tcomments"> 并内联 twikoo.init();否则沿用 Valine 的 <div id="comments">
  • widgets.njk:添加 id="twikoo_comment"<ul> 容器用于展示最近评论
  • layout.njk:向 LOCAL 全局对象注入 twikoo: page.twikoo 页面级覆盖;引入 twikoo.njk partial
  • footer.njk:文章底部新增 #twikoo_visitors 用于显示访问量
  • twikoo.njk [新建]:内联 twikoo.getRecentComments() 渲染侧边栏最近评论
  • script.js:条件生成 CONFIG.twikoo 全局对象,同时将 valine 也改为条件注入
  • pjax.jssiteRefresh() 中加入 Twikoo 初始化逻辑,调用 window.initTwikoo(options)(注意:早期 Twikoo 是 initTwikoo 全局函数)

§ 第二阶段:重构评论模板(2025-10-18)

commit f83055c — 1 文件改动

  • comment.njk:将内联 HTML 提示语封装为可复用宏 commentHead(),Valine 和 Twikoo 共用

§ 第三阶段:修正 API 调用(2025-11-02)

commit d2eb7e2 — 3 文件改动,+4/-12

  • comment.njk:删除了内联的 twikoo.init() 脚本,统一由 pjax.js 接管
  • script.js:将 twikoo vendor JS 路径加入 CONFIG.js
  • pjax.js:API 从 window.initTwikoo() 改为 window.twikoo.init()(Twikoo 1.6.44+ 的模块化 API)

§ 第四阶段:重构评论加载流程(2026-04-19)

commit 7547757 — 9 文件改动,+63/-54

  • _config.yml:vendor 升级到 twikoo@1.7.7
  • layout.njk:删除 twikoo.njk partial 引入(最近评论逻辑已迁移至 pjax.js)
  • footer.njk:修正 Valine visitor 的 enable 条件判断
  • 删除 twikoo.njk:最近评论渲染逻辑移入 pjax.jssiteRefresh()
  • script.js:将 twikoo CSS 路径加入 CONFIG.css
  • 新建 twikoo.styl(15 行):基础容器与图片样式
  • comment.styl:添加 @import "_common/components/third-party/twikoo"
  • page.jsloadComments() 兼容 #tcomments 容器;vendorCss 支持 twikootransition 动画支持 #tcomments
  • pjax.js:重写 Twikoo 初始化——合并 CONFIG.twikooLOCAL.twikoo,调用 twikoo.getRecentComments() 生成侧边栏最近评论 HTML,调用 twikoo.init(options) 渲染评论框。Pjax selector 加入 .twikoo(后在第六阶段移除)

§ 第五阶段:完善样式与 vendor 优化(2026-05-01)

commit bee0115 — 4 文件改动,+2071/-27

  • _config.yml:vendor 从 twikoo.min.js(含 CSS)改为 twikoo.nocss.js(不含 CSS,由主题自定义样式控制)
  • twikoo.styl:从 15 行的基础样式扩展到 2063 行,包含:
    • Element UI 组件样式(Button、Input、Textarea、Loading)
    • OwO 表情选择器样式
    • Twikoo 全部组件样式(头像、输入区、评论列表、回复、管理面板、暗黑模式覆盖等)
  • comment.styl:改为条件编译——仅在 twikoo.enabletrue 时引入 twikoo 样式
  • pjax.jspostFancybox 图片灯箱从 .v(Valine)改为 .twikoo

§ 第六阶段:修复 Pjax 下 twikoo CSS 偶发丢失(2026-06-28)

commit f3d6b3e — 1 文件改动,+1/-1

  • pjax.js:从 Pjax selectors 中移除 '.twikoo'

问题根因.twikoo 容器由 twikoo.init() 动态创建,位于 .pjax 内部。Pjax selectors 中同时存在 '.twikoo''.pjax',且 '.twikoo' 排在前面。Pjax 按顺序处理 selector——先找到旧 DOM 中的 .twikoo 并移除(新 HTML 中无此 class),再整体 swap .pjax。这个提前单独移除触发了 twikoo 内部的 DOM 清理逻辑,导致注入在 .twikoo 容器内的行内 <style> 被一并删除。而 Pjax 时 window.twikoo 已持久存在,twikoo.init() 可能因内部状态标记跳过样式重新注入,最终表现为 twikoo.css 丢失,需刷新页面才能恢复。

修复方案.twikoo 始终是 .pjax 的后代元素,.pjax 整体 swap 已覆盖它,无需单独列出。移除后避免了冗余的提前 DOM 操作,消除了触发 twikoo cleanup 的副作用。

§ 关键设计决策

  1. nocss 方案:最终选择 twikoo.nocss.js 而非 twikoo.all.min.js,将样式控制权完全交给主题,便于定制和暗黑模式适配(通过 twikoo.styl 覆盖默认样式)

  2. Pjax 兼容:博客使用 Pjax 局部刷新,评论组件需在每次 Pjax 导航后重新初始化。pjax.jssiteRefresh() 中检查 DOM 元素存在后重新调用 twikoo.init()。注意 .twikoo 不应出现在 Pjax selectors 中——它由 twikoo.init() 动态创建且始终位于 .pjax 容器内部,由 .pjax selector 统一处理即可;单独列出反而会在 .pjax 整体 swap 前触发提前移除,可能导致 twikoo 注入的行内样式被意外清理

  3. 双系统共存:Valine(enable: false)和 Twikoo(enable: true)的代码同时保留,仅通过配置开关切换,Valine 的配置保留以备未来回退

  4. 最近评论:从独立的 Nunjucks 模板内联脚本 → 迁移到 pjax.js 中统一处理,使用 twikoo.getRecentComments() API 异步获取数据并插入 DOM

§ 相关提交

仓库Commit日期说明
博客301fcd62025-08-19✨ 测试twikoo
博客f30c3222025-08-20✅ 测试调整twikoo资源引用位置
主题4b80e2b2025-08-31✨ 添加twikoo支持
主题f83055c2025-10-18🎨 调整评论模板
博客5d761982025-09-20🔧 更新友链和评论配置
主题d2eb7e22025-11-02🐛 修改 twikoo 配置
主题75477572026-04-19🐛 修复 twikoo 评论系统
主题bee01152026-05-01🧱 调整 twikoo 配置
主题f3d6b3e2026-06-28🐛 修复 Pjax 下 twikoo CSS 偶发丢失

§ 参考链接


  1. shoka主题-更换评论区为twikoo ↩︎

  2. Twikoo 官方文档 ↩︎

  3. twikoo-cloudflare ↩︎

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

星旅人 微信支付

微信支付

星旅人 支付宝

支付宝


在提问之前,你应该学会如何提问