分类
联系方式
  1. 新浪微博
  2. E-mail

个人技术博客研究与思考

前言

在计算机技术领域,博客(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 浏览器,模拟用户行为去发。

这里还涉及到图片上传问题,因此脚本会稍微复杂一点。如果微博改版,还需要重新适配。

这会有几点额外好处:

  1. 可以支持多平台发布
  2. 当文章有更新后,可以自动发微博同步
    1. 如果是更新一篇文章,则附带这篇文章的 url
    2. 如果是更新多篇文章,则附带首页 Timeline 的 url
    3. 还可以吧文章里的图片一同发送到微博上

基于 Flutter 的静态博客生成器

这个生成器我准备用 Flutter 来写,写一个 GUI 工具。

首页布局

首页的上部是感想发布区,跟微博一样,能发布最新感想。

支持插入图片,也支持发布平台。再加一个选项是否自动更新站点。

点击发送,先本地保存,再执行发布操作。

功能区:

  • 添加文章
  • 生成站点
  • 提交站点
  • 本地运行

感想数据存储

感想中的图片,建立一个目录存放。上传的图都是用 UUID 改名,最好压缩一下再保存。

至于数据部分,用 SQLite 或者相关 Flutter 数据库保存一下就好。可以跟文章列表使用同一个数据库。

前端模板仓库

需要建立一个仓库,存储前端展示的模板。

模板列表:

  • 侧边栏
  • 顶栏
  • 底栏
  • 时间线

再有一个 index.html,将各个模板串起来。

样式采用极简化即可,可以考虑使用 tailwindcss。

RSS Feed

RSS Feed 是用于网络订阅的重要形式,提供以下 Feed:

  • 中文 RSS:
    • 总 Timeline
    • 文章 Timeline
    • 随感 Timeline
  • 英文 RSS:
    • 文章 Timeline