为无头像用户提供头像解析
大部分评论区系统(如 Valine、Twikoo、Disqus 等)默认都采用 Gravatar 作为头像源。其工作流程是:系统根据访客留下的邮箱地址,计算出一个唯一的 MD5 哈希值,然后将这个哈希值拼接到 Gravatar 的官方路径或自建的 CDN 路径后,形成一个可访问的图片 URL。浏览器通过这个 URL 去请求头像。
如果 Gravatar 服务器上找不到对应邮箱注册的头像,就会 301 返回一张预设的系统默认图片 /static/img/nobody/80.png。这正是我一直感到不舒服的地方:明明每个评论者都可以拥有独特的视觉标识,却因为这套机制的默认行为,导致大量无头像访客在评论区里顶着千篇一律的“匿名蝴蝶”图标,破坏了页面的整体视觉一致性。
并不是所有中国用户都会特意去 Gravatar 官网注册并上传头像,毕竟这个服务在国内的知晓度和使用习惯都不算高。有人可能会说,那 GitHub 不是也有头像吗?按理说 Gravatar 可以从 GitHub 账号抓取头像,但实际情况是这需要用户提前在 Gravatar 中绑定 GitHub 账号,流程相对繁琐,绝大多数人并不会这么做。
所以最终结果就是,在我博客评论区留言的朋友们,十有八九都顶着那个蓝蓝背景的默认头像。每次翻看留言,看着一串串相同的面孔,心里总归不是滋味。针对这个痛点,其实是有解决方案的——既然默认规则不友好,那我干脆为这些常来留言的熟人写一个私有的头像解析服务。这个方案具备通用性,不依赖某款评论系统,只要是基于 Gravatar 机制的系统都可以适用。
这类评论系统有一个共同的技术特点:评论区是直接嵌入在宿主网页中的 DOM 节点,而不是通过 <iframe> 隔离的独立文档。这就意味着,网站原有的 CSS 样式规则能够穿透并作用于评论区域内的所有元素。利用 CSS 的属性选择器 img[],我们可以筛选出页面上所有图片标签。
若要定位到那些默认头像或特定 Gravatar 头像,只需在中括号内写入 src= 并跟上对应的图片地址即可。更进一步,如果在 CSS 规则中加入 content: url() 声明,原本指向 Gravatar 的图片虽然 HTML 结构中的 src 属性未变,但在实际渲染时,浏览器会强制用新指定的图片替代显示。例如下面这段代码:
1 | img[src="https://seccdn.libravatar.org/avatar/6446a267c0b621de63b89db1aa25e8da"] |
写到这里,我很快又发现了新的问题。我的域名早已配置了缓存规则,其中优先级最高的一条就是“缓存指定扩展名”,而 CSS 文件赫然在列。这意味着,一旦这个包含大量头像替换规则的 CSS 被浏览器或 CDN 缓存,后续任何针对规则的新增、删除或修改都不会立即生效,用户必须强制刷新甚至等待缓存过期才能看到更新。
另外,如果未来不断有新的无头像朋友来留言,我就得不停往 CSS 里追加新的替换规则,这个文件会变得越来越臃肿,维护起来也极不优雅。难道要为了每次加一个头像而修改整个样式表?这显然不够干净,也缺乏扩展性。于是我想到了另一种思路:把映射关系写成 JSON 格式,然后用 JavaScript 从服务器拉取这个 JSON,再动态生成 CSS 注入页面。例如下面这种结构:
1 | { |
现在方案中有了成熟的 CSS 格式和 JSON 格式,接下来就是考虑如何实现功能了。服务器的选择可以非常简单:直接用 GitHub Pages 就够了,因为我只需要存储一些静态文件,并保证它们可以通过 HTTP/HTTPS 被公开访问。整个脚本的核心思想是“无头函数”风格的自执行代码。
它会首先从我的头像服务域拉取 avatar.json 这个映射文件,然后逐条提取出每一个“键”和对应的“值”(即自定义替换头像地址)。拿到这些键值对之后,脚本动态生成一段 CSS 样式,其中每条规则都是用 img[src=""] 选择器匹配原始头像,再用 content: url("") 将其替换成新头像。头像的来源是朋友的博客头像,如果没有则,是他们的 GitHub 账号头像:
1 | (async function () { |
至此,我的“梁栋烨头像联盟”就正式完工了。你只需在自己的博客网站中引入并执行这个脚本,就能共享我的头像解析服务,让那些原本没有头像的评论者自动获得对应的个性头像。当然,这件事还有一个更重要的前提:这里面必须包含你的头像映射才行。不过,比起直接依赖我的服务,我更鼓励你自己动手搭建一套。
毕竟我已经把完整的技术思路和实现细节都写成了教程,自己搭建不仅能完全掌控数据,还能随时按需增删规则。如果你是我博客的长期访客,并且发现你用邮箱留言时始终没有头像显示,非常欢迎点击工单按钮,向我提交头像解析工单。我会把你的邮箱哈希和你想使用的头像地址加入 JSON 映射和服务器缓存中,从此你的每一次留言都将拥有专属的视觉标识。




