个人技术博客研究与思考
前言
在计算机技术领域,博客(Blog)仍然是重要的知识传播方式。对我来说,过去十年间断断续续地写过,但没有坚持下来。我希望今后自己能坚持下去。
在这篇文章里,我记录了自己对于博客的思考。
博客与个人的发展
知识升华
费曼学习法中说到,如果你能把知识给别人讲明白了,你才真正掌握了它。
就跟写代码一样,一段代码,只有计算机运行正确、测试通过,才真正实现了功能。
写博客就是把自己的知识“亮”出来,让别人都能看明白,倒逼自己彻底弄懂。
建立影响力
人在社会上需要建立影响力,有的人向往这个。不向往这个的,为了混口饭吃,也得被迫搞。
对于技术人来说,水平怎么样,博客还是能够体现的。
长期事业
我打算把写博客当作一项长期事业。
随着岁数越来越大,也希望能给自己多找一条出路。
搭建方式
搭建博客的方式有很多,分别说道说道。
博客平台 vs 自建博客
国内外还是有很多博客写作平台的。尤其是国内技术博客,平台很多,氛围也不错。
如果不想在博客程序本身花精力,或者刚开始学技术,选择一个流行的平台就行。博客重要的是内容,是金子在哪里都会发光。博客程序只是一个载体,是形式,本身并不重要。
如果爱折腾,或者对博客的形式有独特审美,通常会自己搭建博客。这也很好,需要注意的仍然是,博客只是一个形式,重在内容。如果你能一周、两周快速搭起来一个博客,支撑自己多年的写作,那就搞吧。如果对你来说,搭建博客本身就是一件需要花费数月的难搞的事情,除非你的目标是学习博客程序开发,否则的话,如果是想写博客,那还是找个现有平台更好一些。
动态博客 vs 静态博客
选择自建博客,首先要选择使用什么博客程序,博客程序主要分为两类:动态博客、静态博客。
动态博客是一个典型的前后端 Web 应用。当用户访问服务器时,首先运行博客程序,博客程序取请求数据库获取数据,再将数据和前端模板做一个整合,最终呈现给用户。现在流行前后端分离的 Web 应用,后端只提供 API,当用户访问时,现在浏览器中加载前端应用(通常使用 React、VUE 编写),前端应用跑起来之后请求后端数据,获取到数据之后进行展示。
静态博客则是有服务器托管一大堆预先生成好的网页文件,当用户访问时,直接把文件展示出来。静态博客的“静态”就是预先生成的意思,用户访问时前后端都不需要执行程序,因此也不存在数据库访问。用来预先生成博客网页文件的程序叫静态生成器。
静态博客比较适合个人博客,因为整体架构比较简单,维护成本也低。
动态静态博客 vs 静态静态博客
随着技术的发展,静态博客又衍生出两类:动态静态博客和静态静态博客,都有点像绕口令了。
静态静态博客
这个就是上一节说的,通过静态生成器预先把博客都生成好,得到一大堆 HTML/JS/CSS,往服务器上一丢,用户纯下载展示即可。
动态静态博客
这个技术衍生自前端的 Server Side Rendering 技术。随着 React、VUE 的流行,Web 应用的功能大大提升。但有利也有弊,这种 Web 应用用户访问的时候,下载下来的都是 JavaScript 程序,要把程序运行完才能看到最终展示结果。这对于 SEO 来说是很不利的,因为有的搜索引擎蜘蛛面对千奇百怪的 Web 应用,不知道你什么时候加载完成,同时运行资源开销也变大,最终导致抓取效果不理想。
Server Side Rendering 即用于解决这一类问题,它对 Web 应用通过一些技术,如无头浏览器,以快照的形式将渲染后的页面保存下来,得到 Web 应用运行完成之后的页面,以此生成静态网页。相当于把动态页面静态化了,SEO 效果大大提升,用户打开时由于不用下载、运行庞大的前端框架,速度有所提升。
但这又带来一个问题,动态 Web 应用静态化之后,又失去了前端框架的强大功能。比如一个网页游戏,静态化之后打开是变快了,但也停留在了那一刻,没有了程序,也就玩不起来了。
于是就出现了动态静态化技术。同样也是生成一份静态网页,提升 SEO 和打开速度。但当用户打开网页后,会在后台继续下载 Web 应用的前端代码。当代码下载完成后,网页会无缝切换到动态版本,相当于又“活”了过来。
动态静态博客就使用了这种动态静态化技术,以 React Static 为例。
我的选择
这些年来我一直使用动态生成器(React Static)来作为博客,因为功能更强大,兼顾各种优点于一身。
但最后我还是回到了静态博客。原因很简单,对于博客来说,不需要太多花哨的功能,能写文章就行。搞得太复杂,根本用不上,而且复杂本身就是一个致命缺点,倒过来限制了我在博客上的发展。
博客写作经验
折腾主题,忽视写作本身
我最初写博客的几年里,沉迷样式主题,WordPress 主题换来换去,反倒没写几篇文章,失去了写作提高的本心。
最近几年,我对样式的要求降到最低,文章排版舒适即可。我也不懂设计,搞不出那种好看的效果,干脆就不折腾了。
别人打开博客,是看文章的。导航清晰,文章排版舒适就行。
在新的博客里,我几乎没设什么样式,看着也挺舒服,打开速度还快。
目标群体
我的博客是技术博客,面向技术人群。内容上除了技术知识之外,还包括技术生涯感悟,和学习感悟。
技术的范围,除了计算机技术外,还包含一些数学、金融知识。
中英文双语
我准备同时支持中文、英文两种语言。既有中文首页,也有英文首页;既有中文文章,也有英文文章。
这是我的一个创意,但是实现起来还是比较复杂的,整体优先级不高。
为什么要支持英语呢?
一方面是想让自己的知识分享给更多的人。
另一方面是互联网上英文阅读群体远远大于中文群体,这样能够提高博客的传播范围。
用 MediaWiki 进行知识管理
这一节跟博客没什么直接关系。博客是一种知识管理形式,但是对于我来说博客过于简单,不能满足我的需求,我需要一种更加强大的知识管理系统。
多年来我一直在探索,各种流行、不流行的知识管理工具试了个遍。最终停留在 MediaWiki,这是支撑维基百科的底层知识管理系统。MediaWiki 既然能够服务全人类最大的知识库,服务我这么渺小的一个人,应该是绰绰有余了。
对于知识管理系统,我最大的感悟是不管使用什么工具,一定要坚持、专一。知识是很宝贵的东西,不要像黑匣子掰棒子那样,掰一个,扔一个。而是要像打扫房间那样,分门别类都归整好,让知识在需要的时候能够立刻捡起来。
基于 MediaWiki 的静态博客生成器
只是一个人闷头记笔记,很难把知识彻底搞明白。就像前面费曼学习法说的,还是得讲给别人听,经得起拍砖。于是我又把博客这件事捡起来了。
由于我使用 MediaWiki 进行知识管理,写博客又要有对应的博客程序,博客程序自有一套写作方式。这就导致我同时要处理两套写作方式,这可太让人难受了。于是我突发奇想,能不能直接用 MediaWiki 导出博客呢?这样我就能留套熟悉的写作体系里,这多方便啊。
现成的程序是没有的,得自己搞了。为了能让自己用的舒服,我希望这个程序是 GUI 的,加上自己一直在钻研 Flutter,于是就有了 RayBlog,一个用 Flutter 编写的 MediaWiki 静态博客生成器。
功能设计
功能梳理
RayBlog 的核心功能还是一个静态博客生成器,只是它的数据源来自 MediaWiki API。另一个特色就是使用 Dart 来写生成器。我是接触 Flutter 之后才了解到 Dart 语言,这门语言很强大,非常不错。
写作还是在 MediaWiki 中进行,想要导出到博客的文章,只需要在 RayBlog 中添加一下文章名称,一键生成网站就完事了。
写作模块想通之后,我又突发奇想,平时我喜欢发微博,能不能在博客里加一个个人微博功能。微博比文章短,平日里的奇思妙想转瞬即逝,只有微博能存下。有了 RayBlog 这个 GUI 工具,加一个微博的本地存储也不是什么难事,于是微博功能也加入进来了。
整体架构
RayBlog 的整体架构如下:
文章写作
在 MediaWiki 中进行文章写作。MediaWiki 新版本推出的 VisualEditor,能够以所见即所得的方式写作,体验非常好。
我对文章的构想是,每篇文章都要持续去完善、打磨,而不是写完了就完了。MediaWiki 的版本管理功能非常适合这件事情。每当我文章有改动后,都可以将改动信息更新到时间线上。
在 MediaWiki 中,可以对文章添加分类,这个分类天然的就是博客分类,因此无需维护博客的结构组织,不会影响到我的 MediaWiki 学习工作流。
英文写作
之所以敢于同时提供文章中英文版本,依赖于 MediaWiki 强大的翻译模块,这一点 MediaWiki 有绝对优势。
翻译过过 Wiki 的小伙伴都知道,MediaWiki 能够基于文章的段落进行逐段翻译,并且有完善的翻译同步更新机制,这一点是其他软件所不具备的。
文章导出
我希望博客最终展示的文章样式,与 MediaWiki 中的样式一致。
我采取的实现方案是:使用 SingleFile 获取文章的单网页形式,之后通过脚本获取到正文内容,将内容与模板进行组合。
这里面会涉及到一些小 trick,比如拼接时组合 CSS 样式,对某些 HTML 标签进行裁剪,不过都很好实现。
连接重映射
文章中会包含一些内部跳转链接,如果是公有文章,则进行 URL 重映射,如果是私有文章,则取消超链接。
图片大小问题
SingleFile 默认会以 Base64 的方式,将文章内的图片编码到网页中,这回导致网页变大。
当然,如果在写文章时控制上传图片大小,整体影响不大。
但最好是能将图片分开保存,加快网页打开速度。这块需要看 SingleFile 是否支持。
整体站点数据
MediaWiki 本身包含了所有文章数据,生成器自己存储的数据越少越好,并且要存那些不会变的数据,比如 PageId。
生成器是一个文章白名单,决定哪些文章可以导出到博客。
在 MediaWiki 里,每个页面都有一个 id,因此生成器只应当存储 id 列表,剩下的数据都动态从 Wiki 中获取。
生成器是一个程序,包含整个站点数据,在生成时根据站点数据进行生成。
站点数据包括:
- 文章列表
- 历史修改记录
- 文章到快照文件的映射
MediaWiki 中的文章会分为共有和私有,只有共有文章会出现在博客中。因此生成器需要维护一个共有文章列表,以文章标题进行标识。
文章数据结构:
名称 | 是否必选 | 说明 | 字段 | 类型 | 备注 |
---|---|---|---|---|---|
中文标题 | Y | 文章标题 | title_zh | String | |
英文标题 | N | 英文文章标题 | title_en | String | 留空表示该文章没有英文文章 |
包含以上内容即可,剩下的会动态调用 MediaWiki API 进行获取。原则还是让 MediaWiki 管理大部分源信息,生成器维护的信息越少越好。
文章历史:
我写文章的时候,会写一点保存一点,而不是全写完了再保存。这会生成多条文章历史修改记录。
生成器需要对历史进行合并工作。如果当天有多条更新记录,则 Merge 成一条。
获取文章摘要
在博客站点首页,需要展示文章 Feed 流。需要获取文章的源信息和文章摘要。
参考 wiki:API:Get the contents of a page
随感
我对随感的定义相当于个人微博时间线,同时出现在博客的时间线上,用于记录自己的一些碎片化感悟。
随感目前只支持中文,如果有好的机翻 API 的话,也可以支持英文。
内容存储
这部分随感内容不存在 MediaWiki 中,而是生成器自己维护。
一键分享微博
有了这个功能,发微博可以不必在微博中,而是在生成器中进行。
微博没有合适的 API,目前想到的办法还是通过 Headless 浏览器,模拟用户行为去发。
这里还涉及到图片上传问题,因此脚本会稍微复杂一点。如果微博改版,还需要重新适配。
这会有几点额外好处:
- 可以支持多平台发布
- 当文章有更新后,可以自动发微博同步
- 如果是更新一篇文章,则附带这篇文章的 url
- 如果是更新多篇文章,则附带首页 Timeline 的 url
- 还可以吧文章里的图片一同发送到微博上
基于 Flutter 的静态博客生成器
这个生成器我准备用 Flutter 来写,写一个 GUI 工具。

首页布局
首页的上部是感想发布区,跟微博一样,能发布最新感想。
支持插入图片,也支持发布平台。再加一个选项是否自动更新站点。
点击发送,先本地保存,再执行发布操作。
功能区:
- 添加文章
- 生成站点
- 提交站点
- 本地运行
感想数据存储
感想中的图片,建立一个目录存放。上传的图都是用 UUID 改名,最好压缩一下再保存。
至于数据部分,用 SQLite 或者相关 Flutter 数据库保存一下就好。可以跟文章列表使用同一个数据库。
前端模板仓库
需要建立一个仓库,存储前端展示的模板。
模板列表:
- 侧边栏
- 顶栏
- 底栏
- 时间线
再有一个 index.html,将各个模板串起来。
样式采用极简化即可,可以考虑使用 tailwindcss。
RSS Feed
RSS Feed 是用于网络订阅的重要形式,提供以下 Feed:
- 中文 RSS:
- 总 Timeline
- 文章 Timeline
- 随感 Timeline
- 英文 RSS:
- 文章 Timeline