博客历史演进

博客历史演进

TinySnow

TL;DR

主要框架

附属模块

演进记录

Hexo 时期

  • 主题太多,选择太多,反而迷失了自我
  • 本身就讨厌 npm 和 node_modules,每次编译很烦,懒得折腾

VuePress 时期

  • 配置项太多了,非常麻烦
  • 同 hexo,用 npm 编译,看到 node_modules 就害怕
  • 编译产物比 hexo 还大

Mdbook 时期

动机

  • 左找右找,正好当时在学 Rust,看到 Mdbook 不错
  • 看了一下官方文档,配置项也特别少,适合自己这种懒人,就改为 mdbook 了
  • 刚开始是出于懒选择的 mdbook,后面发现自己做的工作其实不比其他静态网站生成框架少

困难

  • 切换成 mdbook 本身没什么困难,所有困难主要集中在附属模块上
  • mdbook 本身的困难只有一次,由于 mdbook 版本升级带来的 index.hbs 带来的预置代码变动
  • 详见这篇博客和本博客 Github 上源码关于 index.hbs 带来的更改,另外,Rust 语言圣经也遇到了这个问题,其更改也可以参考

添加附属模块

TOC

  • 切换到 mdbook 首先问题就是没有文章目录
  • 习惯了先浏览文章大纲,建立框架再补充文章细节,很不习惯
  • 浏览了网上所有关于 mdbook 的 toc 方法,都不太满意
  • 大多数是在每篇文章顶部添加 toc 链接
  • 这会占据文章的内容空间,不仅不优雅,每次想跳到另一个章节的时候,还要滚回文章顶部,非常麻烦
  • 正巧当时在学 rust,Rust 语言圣经的 mdbook 里就有 toc 侧边栏,很好奇其实现,就去翻源码
  • 源码在 assets/custom.js,里面的代码大部分都是自定义,toc 侧边栏实现大概是遍历网页的 tagName
  • 还有一些其他附加功能,比如当前页面停留三十秒以上,视为已读过,mdbook 的侧边栏,该文章标题会变灰作为提示
  • 照着实现 toc 和研究 hbs 代码花了很多时间(因为当时不懂 hbs,其实现在也不懂)
  • 途中还遇到了一个怎么都解决不了的难题,最后发现是文件名为 head.hbs,mdbook 会视该文件仅为页面的 head 部分,改成 index.hbs 就好了

评论

  • 评论模块也是参照 Rust 语言圣经,使用 giscus 实现,不过直到现在都没有人用(挺正常的)
  • 评论模块没有太大的问题
  • 之前还附带有 view counter,但是负责 count 的那个网站似乎被炸了,无法完成功能,所以也就把相关代码删了

最近更新

  • mdbook 不按照时间进行倒序排列,而是按照书一样分章节组织
  • 所以改动了哪里也不知道,对于读者来说可能有点烦,每次都要跑到 github 上看代码提交
  • 想了一个折中办法,本地用脚本生成一个 last-updated.md 文件,每次编译后更新
  • 脚本花了一段时间,也犯了比较多的错,直到现在这个脚本都有 bug,而且不通用,不过也懒得改了
  • 每次出 bug 的时候,比如 sed 找不到代表代码块的 ``` 标志,就会直接把 last-updated.md 全删了,再 add && commit,主打一个懒

站内搜索

  • mdbook 的中文搜索和 telegram 的中文搜索一样烂,自己写了太多东西记不到,只记得关键词,搜不到就很烦
  • mdbook 的搜索,根据西方文字自身的空格作为分词符,但中文根本不用空格这种东西,就没法分词
  • 机缘巧合找到了 docsearch,申请了一下,通过了,官方也给了教程怎么搭建
  • 不过 docsearch 很长一段时间我都没用到,因为搜索框死活出不来
  • 本来人就懒,就一直在摆烂,后面有一次有时间了,也实在忍不了搜索之殇了,就好好排查了一下问题
  • 结果发现是 index.hbs 里面,关于 docsearch 的配置少了一个逗号,排查出来自己都想笑,怎么犯了这么低级的错误
  • docsearch 是 algolia 的子服务,要先注册 algolia,然后一步一步配置
  • 甚至要自己配置 algolia 的 crawler(爬虫),自定义爬取的内容,才能加到 algolia 的倒排索引里面,也才能搜索到
  • 本来就懒,简直逆了天了,照着网上稍微配置了一下,自定义了一下就没管了
  • 有一些配置上的 bug 到现在都还没修……
  • docsearch 用起来倒是挺好用
  • 配置在附录,如果有需要可以参考一下

收录网站

  • 后来想把网站加到搜索引擎里,想着可能会帮到别人
  • 一进 Google 和 Bing 的站长工具,又要在 html 的 head 里面加东西,很麻烦
  • 加好了之后,又说需要站点地图才能爬网,当时连站点地图都不知道是啥
  • 随便搜了一个生成站点地图的工具 static-sitemap-cli,还好用起来不复杂
  • 可惜又是依赖 node,用 js 写的工具……
  • 每次本地编译完了之后,就会用这个工具生成站点地图,都在脚本里,自动化一下就可以了
  • 注意,随着文章越来越多,站点地图 sitemap.xmlsitemap.txt 会越来越大,而且 xml 文件每次编译里面的时间都会变,所以 last-updated.md 会越拖越长,这点在写脚本的时候尤其要注意

部署

通过分支部署

  • mdbook 博客搭建好的时候,github pages 的“通过 github actions 部署”还是 experimental(实验性的),采取了主流方案:Deploy from branch(通过分支部署)
  • 但是当时也写了一个 github actions 每次推送的时候自动编译,然后推送到 gh-pages 分支上,就不用自己本地编译了
  • 本地编译一遍主要是因为站点地图和生成 last-updated.md 需要,如果不做这两个工作可以直接推送到 remote
  • 当时用的别人的 actions,自己也没注意到 git 会 tracing 编译后的产物,这些产物都在 gh-pages 里,导致仓库越来越大,仅 .git 文件夹就有 800 多 MB,加上编译产物就有 1G 之大,被迫瘦身

通过 Github Actions 部署

  • 原计划是清理 gh-pages 分支,删除所有 git history
  • 也确实这么做了,从 834MB 减到了 26.8MB,详见这篇博客
  • 但是发现这个时候“通过 Github Actions 部署”已经不再是实验性的了
  • 经过提醒,于是从 Deploy from branch 改为 Github Actions,所以 gh-pages 分支也就用不到了,直接删除
  • 参照 mdbook wiki 里的官方部署教程,自己重写了 Github Actions 文件
  • 感谢一只昀喵辛勤的指导,受教了

使用 Cloudflare Pages

  • 这个想法是源于,经常给国内没法翻墙的朋友发博客内容很不方便,半天转不出来,想方便一下国内的朋友
  • 找了很多静态网站托管服务,要么被墙要么要钱,很搞人,自己甚至还开了一个月腾讯云的静态网站托管服务,结果域名要备案,还要上传 ssl 证书,纯纯大冤种
  • gitea + drone CI/CD,腾讯云,vercel,netlify,Gitee Pages 都试过了,没啥用
  • 最哈皮的还是 Gitee,这玩意儿居然会从源代码里面审查违规内容
  • 而且规则不透明,上一次部署能通过的文章,下一次部署就通过不了了
  • 甚至林清玄的文章都是违规内容
  • 也不告诉你哪儿错了,就告诉你这篇文章有问题,叫人自己排查
  • 开源中国的反馈 repository,里面至少一半多的 issue 都是反应自己无法部署
  • Cloudflare Pages 刚开始用了一下,但是没有 mdbook 的选项,也就不了了之,结果后面搜出来有一种比较 dirty 的做法可以曲线救国
  • Cloudflare Pages 直接导入 Github 仓库
  • 构建配置的框架预设选
  • 构建命令填 curl -L https://github.com/rust-lang/mdBook/releases/download/v0.4.37/mdbook-v0.4.37-x86_64-unknown-linux-gnu.tar.gz | tar xvz && ./mdbook build
  • 构建输出目录填 book
  • 本解决方案参考这篇同样使用 mdbook 作为博客的博文
  • Cloudflare Pages 官方说支持 mdbook 构建,但实际上构建选项里并没有 mdbook
  • 有人在对此的 issue 里提出了一个比较 dirty 的做法,还真有用……
  • 为什么说 dirty,因为这个方法本质上是在 Cloudflare Pages 的构建服务器上,暴力拉 mdbook 的 binary 下来,构建命令当成注入到别人服务器里的 hack 命令用,看一下构建 log 就知道了(构建日志详见附录)
  • 重点在 00:14:26.223 那一行,构建命令实际上是一个 user command,按理来说可以乱填,这里拉 mdbook binary 下来就是不太合规的做法
  • 不过能用就行……
  • Cloudflare Pages 在国内的访问速度其实一般,不过好歹能访问,不像 Github Pages
  • 感谢一只昀喵辛勤的指导,受教了

附录

Algolia Crawer 配置

new Crawler({
 rateLimit: 8,
 maxDepth: 10,
 maxUrls: 5000,
 startUrls: ["https://tinysnow.github.io"],
 renderJavaScript: false,
 sitemaps: [],
 ignoreCanonicalTo: false,
 discoveryPatterns: ["https://tinysnow.github.io/**"],
 schedule: "at 13:14 on Tuesday",
 actions: [
 {
   indexName: "tinysnowio",
   pathsToMatch: ["https://tinysnow.github.io/**"],
   recordExtractor: ({ $, helpers }) => {
    // 去除不想要的 DOM
    $("#sidebar").remove();
    $("#menu-bar").remove();
    $("#menu-bar").remove();
​
    const records = helpers.docsearch({
     recordProps: {
      lvl0: {
       selectors: "",
       defaultValue: "博客",
     },
      lvl1: ["h1"],
      lvl2: ["h2"],
      lvl3: ["h3"],
      lvl4: ["h4"],
      lvl5: ["h5"],
      lvl6: ["h6"],
      content: [
       "p",
       "li",
       "ul",
       "ol",
       "code",
       "span",
       "strong",
       "a",
       "em",
     ],
    },
     aggregateContent: true,
     recordVersion: "v3",
   });
    // 添加语言
    records.forEach((record) => {
     record.lang = "zh-CN";
   });
    return records;
  },
 },
 ],
 safetyChecks: { beforeIndexPublishing: { maxLostRecordsPercentage: 100 } },
 initialIndexSettings: {
  tinysnowio: {
   attributesForFaceting: ["type", "lang"],
   attributesToRetrieve: [
    "hierarchy",
    "content",
    "anchor",
    "url",
    "url_without_anchor",
    "type",
  ],
   attributesToHighlight: ["hierarchy", "content"],
   attributesToSnippet: ["content:10"],
   camelCaseAttributes: ["hierarchy", "content"],
   searchableAttributes: [
    "unordered(hierarchy.lvl0)",
    "unordered(hierarchy.lvl1)",
    "unordered(hierarchy.lvl2)",
    "unordered(hierarchy.lvl3)",
    "unordered(hierarchy.lvl4)",
    "unordered(hierarchy.lvl5)",
    "unordered(hierarchy.lvl6)",
    "content",
  ],
   distinct: true,
   attributeForDistinct: "url",
   customRanking: [
    "desc(weight.pageRank)",
    "desc(weight.level)",
    "asc(weight.position)",
  ],
   ranking: [
    "words",
    "filters",
    "typo",
    "attribute",
    "proximity",
    "exact",
    "custom",
  ],
   highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
   highlightPostTag: "</span>",
   minWordSizefor1Typo: 3,
   minWordSizefor2Typos: 7,
   allowTyposOnNumericTokens: false,
   minProximity: 1,
   ignorePlurals: true,
   advancedSyntax: true,
   attributeCriteriaComputedByMinProximity: true,
   removeWordsIfNoResults: "allOptional",
 },
 },
 appId: "GX9RTL51BH",
 apiKey: "PlaceHolder",
});

Cloudflare Pages 构建日志

00:14:23.159 Cloning repository...
00:14:24.014 From https://github.com/TinySnow/TinySnow.github.io
00:14:24.015  * branch     3685b9c14d244ab2a2888d820486e261e5174aea -> FETCH_HEAD
00:14:24.015 
00:14:24.139 HEAD is now at 3685b9c Added some Pharmacology content
00:14:24.139 
00:14:24.222 
00:14:24.222 Using v2 root directory strategy
00:14:24.250 Success: Finished cloning repository files
00:14:25.960 Checking for configuration in a wrangler.toml configuration file (BETA)
00:14:25.960 
00:14:26.071 No wrangler.toml file found. Continuing.
00:14:26.223 Detected the following tools from environment: 
00:14:26.223 Executing user command: curl -L https://github.com/rust-lang/mdBook/releases/download/v0.4.30/mdbook-v0.4.30-x86_64-unknown-linux-gnu.tar.gz | tar xvz && ./mdbook build
00:14:26.245  % Total % Received % Xferd Average Speed Time Time  Time Current
00:14:26.246                 Dload Upload Total Spent Left Speed
00:14:26.455 
 0  0 0  0 0  0  0  0 --:--:-- --:--:-- --:--:--  0
 0  0 0  0 0  0  0  0 --:--:-- --:--:-- --:--:--  0
00:14:26.831 mdbook
00:14:27.065 
 0 5031k 0 32768 0  0 59463  0 0:01:26 --:--:-- 0:01:26 59463
100 5031k 100 5031k 0  0 6130k  0 --:--:-- --:--:-- --:--:-- 18.1M
00:14:27.136 2024-05-02 16:14:27 [INFO] (mdbook::book): Book building has started
00:14:27.146 2024-05-02 16:14:27 [INFO] (mdbook::book): Running the html backend
00:14:36.384 Finished
00:14:36.385 Note: No functions dir at /functions found. Skipping.
00:14:36.385 Validating asset output directory
00:14:37.224 Deploying your site to Cloudflare's global network...
00:14:42.448 Uploading... (1254/1254)
00:14:42.449 ✨ Success! Uploaded 0 files (1254 already uploaded) (0.65 sec)
00:14:42.449 
00:14:43.060 ✨ Upload complete!
00:14:45.569 Success: Assets published!
00:14:46.752 Success: Your site was deployed!


Report Page