summaryrefslogtreecommitdiff
path: root/content/article/site-report-4.md
blob: 3c9ea4ccea17c417db2daed6259a1dc57a8cb001 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
+++
title = "极客死亡计划书 IV"
subtitle = "Be indie and be social."
slug = "site-report-4"
tags = [
    "联邦宇宙",
    "IndieWeb",
]
categories = "极客死亡计划书"
date = 2026-02-01T23:53:07
draft = false
toc = true
toot = "https://akk.eltr.ac/objects/df061cb1-01d5-4308-ac7b-658adb41df09"
url = "/posts/site-report-4/"

+++

[书接上回](/posts/site-report-3/#:~:text=%E6%88%91%E5%9C%A8%E8%BF%99%E9%87%8C%E5%85%88%E7%95%99%E4%B8%80%E4%B8%AA%E5%BC%95%E5%AD%90%EF%BC%8C%E5%85%B3%E4%BA%8E%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%8F%98%E6%9B%B4%EF%BC%8C%E5%A4%A7%E6%A6%82%E4%BC%9A%E7%95%99%E5%88%B0%E3%80%8A%E6%9E%81%E5%AE%A2%E6%AD%BB%E4%BA%A1%E8%AE%A1%E5%88%92%E4%B9%A6%20IV%E3%80%8B%E6%9D%A5%E5%86%99%E4%BA%86%E3%80%82),先前的一期《极客死亡计划书》最后留了个有关评论系统的引子。如你所见,目前我已经完成了评论系统的变更:**我把它删掉了**。当然,我提供了其他交流的途径,你仍然可以与我和其他读者,像在正常的评论系统中一样讨论文章内容。今天的文章将会解释评论系统变更的原因、新的与读者互动的方式、我对独立博客的评论的想法,以及读者还可以了解到如何使用新的「交互」系统。<!--more-->

## 本博客评论系统的历史变更

从 Typecho 换到静态博客之后,给博客添加评论系统就变得很棘手。本质上,评论是「用户生成内容」(User-generated content),涉及到用户向服务器发送 HTTP 请求,服务器响应请求后将评论数据写入数据库并返回状态信息,其他用户访问页面时,服务器会从数据库读取评论数据。显然,对于静态网站而言,服务器和数据库都是不存在的,所以就需要外接一个评论后端。

记得早年间我还使用过 [Gitalk](https://github.com/gitalk/gitalk),一个基于 GitHub Issues 的评论系统。后来 GitHub Discussion 推出,更符合「讨论」这个逻辑,于是 [Giscus](https://giscus.app/) 也就诞生了,几天前,我还在使用 Giscus 作为博客的评论系统。这两个评论系统都依托于 GitHub API,需要 GitHub 账号才能使用。用户也不真正拥有自己的数据,所有的讨论实际上都发生在 GitHub 这一个平台上。上一期极客死亡计划书我也表达了对 Giscus 的批评——依赖于 `<iframe>`,使得数据交换、优化加载速度和自定义都变得很难。不过,毋庸置疑地,Giscus 非常易用,不需要自己维护后端,使用 GitHub 登录也避免了绝大多数的垃圾邮件。

在此之前,我也有使用过 Valine 和 Waline,它们都依托数据库,可以很轻易地在 LeanCloud 上部署(不过就在最近,LeanCloud 已经停止服务了),也可以自托管。我也有听闻,并且作为访客使用过其他人网站上的 Twikoo、Artalk 和 Remark42。这些评论系统的设计各有特色,但共同之处是你需要自己搭建并维护后端和数据库,这不难,但必然会增加网站架构的复杂性。

动态博客加上评论系统是顺带的事情,但对于静态博客来说,为静态网页加上动态的内容,还要单独维护一个后端,就显得有些不符合静态网站这种架构的哲学了——*既然你都选择维护额外的后端和服务器了,那你为什么不直接用动态博客呢?反正都要有后端的,一个轻量的 CMS 并不会占用太多资源。*

本来我是为了摆脱 Giscus,才开始思考要不要自托管评论系统这件事的,但我很快意识到我并不想增加网站的复杂性。如果使用传统的填写称呼、电子邮箱和网址直接评论的方式,就会有身份被冒充的风险(获得某人的邮箱地址简直是轻而易举),而且垃圾信息也很难避免,需要做额外的措施。如果使用必须登录才能评论的方式,的确能解决上述问题,但我希望自己的个人信息被上传到尽可能少的地方,而且如果要变更邮箱地址,四处更改账号信息也是吃力的活儿,我的上网原则之一是「如非必要,绝不注册」,我当然不希望我的读者必须额外注册才能评论,维护一个用户认证系统也会让维护后端变得更复杂。

显然,这已经告别了绝大部分的评论系统了。

为了认证用户且不必维护新的认证系统,那么最简单的方式当然是使用一个现有的认证系统。我指的并不是 Google 登录、Apple 登录和社交媒体账号登录这种方案,因为实际上我仍然需要将用户的登录信息储存在自己的数据库里。最好是使用去中心化的身份系统,比如 OpenPGP 密钥对。

## Email and OpenPGP

诚然,OpenPGP 也受到批评,它有时会[失效](https://gpg.fail/)。不过,在本文中,我们**假定**它是有效的,~~因为我还没有开始了解和研究它为什么有缺陷~~,而且,OpenPGP 也有替代品,你可以把本文中提及的 OpenPGP 理解为「OpenPGP 和与之类似的加密标准」。

在上一期《极客死亡计划书》中,我提到,电子邮件的发信一般是可信的。如果你收到了来自 `hi@eltr.ac` 的邮件,那么发信人基本可以确定就是 Eltrac。尽管也有伪造发信地址的技术手段存在[^1],但 SPF、DKIM 和 DMARC 等反制手段也很成熟了。在发信协议之上,也可以使用 OpenPGP 加密或者签名邮件[^2],使用公钥验证再次验证发信人的身份。

所以,如果能开发一种基于电子邮件的评论系统就太好了,大多数用户都有电子邮箱账号,而且电子邮箱是去中心化的,大家可以使用自己熟悉的邮件服务进行评论。我的设想是,评论者向一个电子邮箱地址发送邮件,比如 `comment@geedea.pro`,邮件主题是页面标识(标题、URL 或者别的什么 ID),而邮件正文是评论内容。邮件服务器在这个邮箱收到特定格式的邮件后,如果没有问题,就把它当作有效的评论处理,存入数据库或者通过 CI/CD 工作流直接写入博客源代码。如果用户有提供签名,验证身份之后还可以像 Git commit 那样,在前端显示 `Verified` 或者一把小锁,表示评论者的身份是可靠的。技术上来讲,这完全可行。用户交互层面也不会很麻烦,因为可以使用 `mailto:` 链接,帮用户自动填写邮箱地址和邮件主体,用户只需要在自己的邮件客户端里撰写评论正文。

不过,我仍然需要一个用来接收和处理邮件的后端,把邮件内容写入博客显然也会增加网站架构的复杂度。通过发送邮件在网站上发送评论,仔细想想,其实非常反直觉,用户需要在不同的界面之间跳转,而且邮件发送和服务器处理会造成时延,用户不能立刻得到反馈。

这个方案最终还是没有被我采用,尽管头脑风暴的过程很爽。兴许写下来之后,会有人觉得有用吧。

## Let's ActivityPub

谈到去中心化,那就不得不谈联邦宇宙了。尽管我并不了解 ActivityPub 规范和设计思想,但我大概了解联邦宇宙的工作方式。简单来说,所有人都可以待在自己选择的服务器上,并且与其他服务器通信,构成「互联网」。联邦宇宙并没有提供密码学意义上的身份认证,但至少伪造身份并不容易,尤其是对于那些拥有自己的域名,并且使用这个域名自建联邦宇宙实例的人来说。

比起一对一的电子邮件,开放的联邦宇宙更适合「公开讨论」。将联邦宇宙用作评论系统可以一举两得地解决身份验证和评论数据管理的难题,毕竟这两部分的复杂度都已经被成熟的联邦宇宙软件解决了。其实这和 Giscus 的逻辑差不多,如果使用 Giscus,讨论实际上在 GitHub 上发生,用户也使用 GitHub 账号登录,Giscus 所做的只是把 GitHub 的讨论和万维网页面映射关联起来。区别在于,使用联邦宇宙作为评论系统的话,尽管讨论也在博客之外的地方发生,但联邦宇宙是开放的,不受 GitHub 这样的中心控制。

如果为了评论而专门开发一个实现了 ActivityPub 的软件,显然有些没必要。符合直觉的做法是,文章发布后,将页面 URL 发布在联邦宇宙账号上,关注者看到之后就能直接对帖子进行互动(点赞、表情回应和评论)。这个帖子(ActivityPub 对象)就作为网站页面在联邦宇宙上的「载体」,对这个帖子的回应就被视为对原文的回应。

听起来只需要让访客到联邦宇宙上讨论文章内容就好了,不过要怎么把联邦宇宙上的讨论内容展示在网站上呢?一是可以在前端通过 API 动态抓取,二是可以用 CI 工作流每隔一段时间抓取一次数据,如果有更新就提交到 Git 仓库,Hugo 直接渲染保存在源码里的数据。那一开始要如何把联邦宇宙帖子和网站页面关联起来呢?一是可以每隔一段时间扫描指定账号下的帖文,检查是否有指定网站的 URL,如果有,就把这个帖子和帖子引用的链接关联起来;二是可以在网站源代码(比如 Markdown 文件的 Frontmatter)中指定帖文链接,直接请求这个帖文的数据。

听起来还是要从头开始搓一个工作流呢,增加复杂性看来是不可避免了,除非有另一个现成的解决方案?

## Now, Webmention

我在[第 60 期周刊](/posts/weekly/60)中提过,博客实现了 [Webmention](https://www.w3.org/TR/webmention/) 的接收;又在[第 63 期周刊](/posts/weekly/63)中描述了通过自动化工作流从 `webmention.io` 拉取 Webmention 数据并保存在 Git 仓库,让 Hugo 直接渲染本地数据文件的做法。简而言之,博客现在已经能够很好地接收并展示 Webmention 了,并且不会牺牲 Hugo 作为静态博客的速度优势和简单性。

[Brid.gy](https://brid.gy/) 很好地实现了前文提及的「定时扫描联邦宇宙账号和网站页面并建立映射」的做法,简单来说,只要用联邦宇宙账号登录 Bridgy,它就会抓取与你有关的互动,比如有谁点赞了你的某篇帖子、有谁回复了你的帖子等等。与这些互动直接关联的帖子,如果包含一个 URL,Bridgy 就会尝试向这个网址发送 Webmention。

![Bridgy 的用户页面,显示了一系列抓取到的联邦宇宙互动,其中的一些找到了对应的 URL 并且向网站发送了 Webmention](https://img.eltr.ac/geedeapro/posts/site-report-4/1Capture_2026-02-01_22.22.44.png)

由于博客已经能够接收 Webmention,我也就不需要再想办法把联邦宇宙上的互动信息显示在博客上了,只需要渲染 Webmention 就好。

这种方案有缺陷,比如 Webmention 的同步有延迟,并且只能展示与帖文直接关联的互动,所以只能展示一级评论(评论的评论,也就是子级评论,由于是对回复帖文的互动,并不是直接关联的,所以不会被抓取)。不过,我认为这很符合 Webmention 的逻辑,即「有人在万维网的另一个地方提及了这个页面」,也就是说,这并不是评论系统的替代,而是告知读者「在另一个地方有人讨论了这篇文章」,如果读者感兴趣,就可以通过链接前去查看。

## “所以,怎么点赞和评论你的博客?”

> [!warning]
> 这一小节的内容已经过时,目前博客不再与联邦宇宙桥接,但依然使用联邦宇宙作为评论文章的主要方式,只是互动不会展示在网站上了。

如果你现在移动到页面最下方,就能看到这样一个条:一个写着「+」的按钮,右边是一些人的头像,最右边显示的是喜欢了这篇文章的人的数量。点击按钮,就能看到一个浮窗,里面有两个表单。

![](https://img.eltr.ac/geedeapro/posts/site-report-4/1Capture_2026-02-01_22.37.50.png)

第一个是联邦宇宙表单,你可以在这里填入你的实例域名,比如 `c7.io` `mastodon.social` 或者你自己的域名,点击「打开帖子按钮」,浏览器就会打开 `https://<实例域名>/authorize_interaction?uri=<这篇文章对应的帖子链接>`,效果就是在你的实例上打开这篇文章对应的帖子。不过,这个功能我自己测试的时候有点问题,还请更了解 ActivityPub 的读者给我一些反馈。你也可以选择留空,这样就会直接打开源地址。

值得一提的是,很多页面上都不会显示联邦宇宙表单,原因是页面发布的时候我还没有开始使用联邦宇宙,所以没有关联的帖子(当然你仍然可以在联邦宇宙上 `@` 我并附加文章链接,来与我交流),另一种可能是你来得太早,我还没有发布对应的帖子。

第二个是 Webmention 表单,如果你撰写了一篇文章,并且在文章中提及了某篇文章(指页面中**包含指向这篇文章的链接**),就可以在这篇文章下方的 Webmention 表单里输入你的文章的 URL,点击发送即可向我发送 Webmention。你会被跳转到 `webmention.io`,如果成功就只会显示一串 JSON 数据,我之后可能会优化一下交互反馈。如果你使用的是 WordPress[^7] 或者别的什么实现了 Webmention 发送的博客软件,这个过程就是自动的,你无需手动提交 Webmention,具体能否自动发送还请读者自行研究。

简单来说,如果你要点赞或讨论某篇文章,请点击「打开帖子」并在联邦宇宙上对帖子进行点赞或讨论;如果你在你的网站上提及了我的文章,就可以向我发送 Webmention。

### 什么是联邦宇宙?我可以注册吗?

联邦宇宙是 Mastodon、Pleroma、Misskey 等实现了 ActivityPub 协议的开源自由软件组成的社交网络,你可以理解为去中心化的 Twitter(也有实现了 ActivityPub 的 YouTube 和 Instagram 替代)。你可以在任何一个联邦宇宙服务器上注册账号,或者自己搭建服务器,在任意一个服务器上登录都可以与任何一个联邦宇宙中的账号互动[^3]。

我自己的实例([Eucalyptus](https://akk.eltr.ac))是不开放注册的单人实例,以下是公共实例,你可以选择一个加入,然后就可以和包括我在内的整个联邦宇宙互动了。

* [mastodon.social](https://mastodon.social/),Mastodon 的官方实例
* [mas.to](https://mas.to/)
* [c7.io](https://c7.io/),一个不错的 Mastodon 实例,我曾经在这里待过
* [misskey.io](https://misskey.io/),Misskey 的官方实例
* [seafoam.space](https://seafoam.space/),一个开放注册的 Pleroma 实例

你也可以在 [FediDB](https://fedidb.com/servers) 上查看较完整的服务器列表。如果你对联邦宇宙一无所知,可以访问[这个网站](https://jointhefediverse.net/?lang=zh-hans),这里有直观的介绍。

有了一个联邦宇宙账号,你就可以点赞和评论我的帖子了。按照上述方式在你的实例上打开我的帖子,就像 Twitter 一样操作吧!当然,有了联邦宇宙账号之后,你能做的事情非常多,你可以去关注更多的人,也很容易在上面认识新朋友。

### 什么是 Webmention?

Webmention 和 ActivityPub 一样,都是 W3C 标准。我相信你一定有在微信群聊和社交媒体等平台上 `@` 某人的经历,我们把 `@` 称作「提及」,`@eltrac` 就是「提及 Eltrac」。显然,「提及」是局限于平台的,你只能提及和你在同一个社交媒体平台上的人。Webmention 直译为「万维网提及」,也就是发生在网站之间的「提及」。假设 A 在自己的网站上发布了一篇文章,B 觉得这篇文章写得不错,也有感而发写了一篇文章,并且在这篇文章里「提及」了 A 的文章。正常来说,A 并不会像在微信群聊里被「提及」了一样收到通知,但 Webmention 补足了这一点——如果你在自己的网站上提及了某人,而对方开放了接收 Webmention 的端口,你就可以向他发送 Webmention 通知;对方不仅能收到通知,还能把提及的内容展示在自己的网站上。

如果你在联邦宇宙账号上和我互动,你的点赞和评论就会通过 Webmention 的形式同步到我的网站上。你也可以不在联邦宇宙上与我互动,而是通过撰写文章页面的方式提及我的某篇文章。如果你使用 WordPress 等博客程序,你的网站大概会自动发送 Webmention;如果你不能自动发送 Webmention,你就需要手动在页面下方的表单里提交你的回应文章。

或者,你也可以用上古神器 `curl` 发送,毕竟 Webmention 实际上就是一种特殊的 HTTP 请求。

```shell
curl -i
    -d "source=<你的文章URL> &target=<目标URL>"
    https://webmention.io/www.geedea.pro/webmention
```

如果你想要自己的博客能够接收 Webmention,你可以参考 Taxodium 的[这篇博客文章](https://taxodium.ink/add-webmention-to-blog.html)。[^4]

### 邮件联系可以吗?

当然!非常欢迎!我很喜欢和人用邮件这种方式交流。

之前有一些读者询问能否添加我的微信好友,我毫不犹豫地拒绝了。第一是我讨厌微信,我只在不得不使用的场景下使用这个软件,比如和现实中的朋友交流、工作和付款等等;第二是我希望尽可能保持匿名,我的互联网生活和现实生活是分开的,我的微信好友位一般只会留给现实生活中的朋友。之前我还会使用 Telegram 和网友交流,现在也弃用了。[^5]

如果你偏好一对一的沟通,我最推荐的方式是通过邮件联系。不必注重格式,只要写清楚主题,交代清楚来意就好,就算是随便打个招呼我也会觉得很开心。~~相反,如果是给我发微信,就算是给我发钱我也会觉得压力山大;如果是打电话,那我会在做好接电话的心理建设之前大声尖叫。~~

这是我的邮箱地址:`hi@eltr.ac`。你也可以在文末的互动浮窗里点击「📧 也欢迎邮件交流!」这行字,这是一个 `mailto:` 链接,点击后会打开你的默认邮件客户端,并且会自动帮你填好邮件主题(`Re: <文章标题>`)。

## 论独立博客的评论

去年二月份我写过一篇《[论独立博客的评论](/essays/论独立博客的评论/)》。这篇文章下也有不少人分享了他们的看法。这些评论原本是保存在 GitHub Discussion 上的,你现在可以到页面底部点击最下方的一行字,展开旧的评论数据,我都有保留。翻到这篇文章的时候我也有思考,我这么放弃了传统的评论区,是不是也放弃了这样有趣的交流呢?

我想我必须试试才知道。那篇文章中有提到 Owen 把 Telegram 群组代替评论系统当作一场实验,那么我在今年年初开始用联邦宇宙和 Webmention 代替评论系统,也算是一场不错的实验。我也很期待,我在这篇文章关联的联邦宇宙帖子上,以及发送到我网站上的 Webmention 里,也能看到同样有趣的交流和回应。

最近有读到一些博主对评论的思考,尤其是早就禁用了评论区的博主,再加上我最近也收到了我不太喜欢的评论。我又开始思考,评论区真的是最适合我的交流形式吗?我回忆起最近让我感到最愉悦的交流,也包括那些让我受到启发的留言,几乎全都来自联邦宇宙和电子邮件(那些给我发邮件的读者,谢谢你们!)。我也有想过要不要写一篇文章,谈谈我希望收到什么样的评论,不希望收到什么样的评论[^6],但仔细想想,我讨厌的是不能完全尊重我和我的观点的评论,如果评论者都不尊重我的观点了,他会同意我有关「我希望收到什么样的评论」的观点吗?这显然不会起作用。

此外,我还经常发布大多数人并不在乎的内容,比如法国文学的书评、塔罗牌的牌意解析,未来大概还会有…… Lisp 的学习感受?而这样的内容往往只能收到很少的评论,但它们又是我非常感兴趣的话题。原来的评论区会让我感到压力,而现在,即使一篇文章没有收到太多的回应,我也不会那么在意了,因为评论区都被我砍掉了。联邦宇宙互动和 Webmention 较少,是可以理解的,毕竟使用这些技术的人本来就比较少。抱着这样的心态,我大概会更有勇气写自己感兴趣的文字,~~虽然我大概还是会阴暗地在 GoatCounter 仪表盘查看某篇文章的访问量~~。

至于我在写作之外,能和读者以及其他的创作者通过新的交流方式碰撞出什么火花,那就在 2026 年一起好好见证吧!

[^1]: 参见:[Email Spoofing - Wikipedia](https://en.wikipedia.org/wiki/Email_spoofing)


[^2]: 一般来说,不建议发送加密的邮件,因为不符合标准。有关为什么不应该加密邮件内容的讨论,可以参考 [Migadu 的说法](https://migadu.com/procon/#not-encrypted)。况且,有了 SSL/TLS 的保护,邮件在发送过程中往往是安全的。

[^3]: 除非有管理员封禁了某个实例的情况,但一般来说不会。

[^4]: 是的,我会给他发 Webmention 的。

[^5]: 如果你还是更喜欢即时通信工具,你可以在 Matrix 上找到我,这是我的账号:`@eltrac:eltr.ac`


[^6]: 比如,那些显然没有读完我的文章,也对我没有太多了解,就凭借零碎的信息开始想象我的人物形象,给我贴标签或者对我进行说教的。哪怕没有恶意,也有爹味溢出屏幕的。这就是我不希望收到的那一类。

[^7]: 2026 年 2 月 23 日,修正:似乎 WordPress 不会默认发送 Webmention,需要安装[插件](https://wordpress.org/plugins/webmention/)。我没有使用过 WordPress,所以不了解详情。