把博客变成一本可离线下载的电子书
记得之前看到过一篇文章,讲的是如何在死后保持自己的个人网站一直在线,文章地址我忘记存了,只记得文章里分析了各种选项,比如靠死后的信托基金什么的,都是些让我听的一愣一愣的选项,因为我既不懂什么是信托,也不懂什么是基金。不过即使如此,那篇文章的最终结论依然是很难保证个人网站在死后长期在线。因为单就域名来说,每次续期的最长期限就是10年,如果我死了,并且我有子女,幸运的话他们可以帮我续费几十年,之后的子孙后代就很难说。整个互联网发明也才不过几十年,还没有人有足够的经验能预测这件事,而且照人类这个活法,指不定哪一天就先毁灭了自己。
再说回网站,如果你的个人网站还不幸是个动态网站的话,那死后的可维护性就更难了。不能指望自己的孙子刚好也懂PHP吧。
所以一个相对比较可行的办法,至少是使用静态网站,因为静态网页的托管足够简单,成本低,很多大公司都有免费方案。假如我相信 Github
在我死后不会倒闭,那我可以选择把静态网站免费托管到Github上,然后祈祷Github静态网站托管的免费政策不要发生变化,同时也希望我不要意外死亡,以便我可以在死前几个月将我的个人网站的域名,301永久跳转到theowenyoung.github.io的子域名上,同时把旧的个人域名续期10年,以便所有(机器)人有充足的时间切换到新的子域名。
上述方案的核心就是寄希望于 Github 不要倒闭,如果我死后有在天之灵的话,我当然会保佑Github 基业长青,但是如果我的修行不够,那也许死后在另一世界自身都难保呢,何谈保佑 Github 呐。
所以啊,想要不依赖第三方服务,还是得能做到离线化才行。按理说目前的博客已经是离线化的了,比如你可以git clone git@github.com:theowenyoung/blog.git这个博客的源文件到本地,然后执行make install,
make serve就可以本地离线查看了,但是这就引入了额外的复杂性,很少有人真的乐意做这件事。一个折衷的办法是在构建静态博客的时候,同时也把整个博客打包成一本电子书供读者下载,这样的话,别人本地就有了一个很方便的备份,相当于是一种去中心化的分发。epub和pdf格式是其中两种很方便、也很通用的格式,甚至可以嘱咐家人在我死后把这本书放在区块链上(如果他们会的话!),甚至可以打印出来,装订成册,埋在北极的冻土层里,比区块链还保险。
听前面这段话,会感觉我这人真是天大的自恋狂,我的破博客能有多么的重要以至于死后都要保持在线。其实不然,真实情况恰恰相反,我博客的内容十分肤浅,我要是死了,我恨不得永久抹除这些让人尴尬的文字呢,所以我怎么会想让这种东西永久在线呢!
所以这只是概念验证,也许能提醒某个真正有东西的博主开始考虑用持续集成把自己的博客打包成一本电子书。而我明天则要找时间研究下,如何让谷歌在我死后删除有关我的所有结果。
具体方案🔗
注意:我的最终方案和与我的博客本身非常耦合,并不具备普遍性,所以这不是一个教程,只是一个实现的参考。
我以为这种需求很常见,应该能很快找到成熟方案,但是竟然没找到什么特别成熟的方案,看到一个bookdown的方案,但是真的看不懂,不懂什么是RMarkdown, 然后还被它的说明 里让我下载个IDE才能运行的要求吓到。
最后我用了 rust 的 mdbook ,同时配合插件 mdbook-epub, mdbook-pdf生成epub和pdf,再加上自己写了一个deno 脚本去过滤/组织博客的文档,以及替换markdown的内部链接等等。当博客更新的时候,用github workflow去打包最新的电子书并上传。
最终的成果是生成2本电子书:
- https://book.owenyoung.com/ - 只收录了我指定的文章
- https://archive.owenyoung.com/ - 按年份打包所有的文章
第二本电子书由于包含全站文章(以及图片),size有点大,epub版本目前是30M,pdf版本是38M,所以没有上传到我的静态网站上(cloudflare最多允许25MB的静态资源文件),而是用Github Actions 生成了一个Github的release 资源。
- name: Update release
uses: johnwbyrd/update-release@v1.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
release: book
files: |
./owen-blog-dist/owen-blog.pdf
./owen-blog-dist/owen-blog-html.zip
./owen-blog-dist/owen-blog.epub
./owen-blog-archive-dist/owen-blog-archive-html.zip
./owen-blog-archive-dist/owen-blog-archive.pdf
./owen-blog-archive-dist/owen-blog-archive.epub
一套弄下来,比我想象的工作量要大,主要是要处理一些边缘情况,但是我最喜欢deno的一点,就是我能在一个脚本文件内完成所有的处理。
mdbook 要求markdown的文件为如下格式:
# Title
Body.
本质就是纯markdown文件,而zola的markdown格式是有frontmatter的:
---
title: Title
date: 2022-10-11
---
Body.
这个在Deno里比较好处理,官方的std直接就提供了frontmatter的解析:
import { extract } from "https://deno.land/std@0.159.0/encoding/front_matter.ts";...剩余内容已隐藏