

友链这东西,说出来有点浪漫。
2025 年了,个人博客基本没有什么流量,更多像是一座座散落在海上的小岛。
偶尔有海风吹过,但大多数时候,就是悄悄发光、自娱自乐。
而友链……就像是在这些小岛之间铺上一条条细细的桥。
你看不到桥的尽头,但知道那里至少还有一个同样孤独、同样固执的人。
为什么拖了这么久才开放友链申请?#
刚写博客那阵子,我其实没太敢申请友链。不是因为不想被发现,而是因为我真的是那种比较内向的类型。
内容少也不自信,总觉得“我这样去申请友链,会不会显得很冒失?”
再加上每个人对友链的理解都不太一样:
- 有人只收特定领域的高质量博客
- 有人觉得必须线下认识
- 也有人坚持要有一定的线上互动次数
即便对方没有列要求,我心里还是会嘀咕:“我们不熟,贸然提出会不会不太礼貌?”
传统的友链申请方式大多是:留言、邮件,或在 GitHub 提 issue。看似简单,但对我这种“有自助收银台绝不走人工”的 I 人来说,其实是需要一点点勇气的。
直到有一次,我在看一位老师的博客时,看到有人问:“这么多友链,你是怎么维护的?”
老师回: “脚本。”
那一瞬间我有点被点醒了:
既然我不好意思主动打招呼,那是不是可以先让别人跟我打招呼不要那么困难?
说干就干:自动化友链要处理些什么?#
为了做到“自动添加”,其实需要处理的事情很简单:
- 对方网站必须能访问
- 不能让广告站点钻空子
- 对方真得挂上了我的友链
于是我要求申请方提供友链页地址,然后脚本负责验证:
- 确认主站是正常可访问的
- 主站域名与友链页域名一致(避免广告跳转)
- 友链页中确实存在我的网站
通过就添加,没通过就直接拒绝,简单粗暴但有效。
技术实现:我是怎么做的?#
1. 友链数据剥离成 JSON(重点)#
一开始我的友链是写在 Astro 的页面里的。
但这意味着:
改一个字 → 就得重新打包部署
非常麻烦。
后来改用 SSR(服务端渲染) 后,我意识到:
完全没必要把友链打包进页面里。
数据完全可以在服务端“即时读取”。
于是我把友链抽成一个 links.json 文件,并且 不再使用 import 引入它。
因为一旦 import,它就会在构建时被写死。
正确的方式是:
const raw = await fs.readFile(linksPath, 'utf-8')
const { friends } = JSON.parse(raw)ts这样:
- JSON 是独立的数据源
- SSR 每次渲染页面都会读取到最新内容
- 修改 JSON = 友链立即生效
- 无需重新打包
这也是我把友链从页面剥离出来的根本原因。
2. 头像检查 + 上传 OSS#
用户提交的头像链接永远无法保证靠谱:
- 有的不是图片
- 有的没 content-type
- 有的会失效
我的解决方案是:
- 先判断扩展名是否是图片
- 再通过请求检查 content-type
- 最后统一上传到 OSS
我用的是 ossutil
因为它是 CLI,不需要把 AccessKey 写进代码里,对我这种 Node 不熟练的人来说更安全。
(当然也可以不用 OSS,不过不管是速度还是稳定性都不如 OSS 省心)
3. 检查对方是否挂了我的链接#
为了避免“我挂你,你不挂我”或者广告的情况出现,脚本会:
- 访问对方主站
- 检查友链页是否同域
- 抓取页面,看是否包含我的链接
确认通过,才会添加。
4. 自动更新 JSON + 顺手 Git 提交#
友链通过验证后,脚本会:
- 把条目写入
links.json - 自动执行
git add → commit → push
因为是 SSR,页面下一次请求时就会看到最新的友链数据。
不需要重新打包,也不需要重新部署。
整个流程非常轻量。
SSR 这个环节的重要性#
在写脚本之前,我也想过纯静态博客能不能实现自动化友链。
答案是:能,但非常折腾,不值得。
纯静态的问题:
- 页面打包后就是死的,无法在服务端执行校验逻辑
- 用户无法直接让服务器写入文件
- 想走 GitHub Actions,需要用户先有权限 push(显然不行)
虽然理论上可以:
- 表单提交 → 云函数写文件 → 云函数 push GitHub → Actions 构建 → 部署
但整个链路太长太容易出问题。
相比之下:
SSR:写一个 API 就全部搞定#
Cloudflare、Vercel 都能跑 SSR
甚至没服务器也能跑
所以最后我还是选择了最干净、最好理解、扩展性最高的方案:
在 SSR 里加一个接口,让它帮我跑脚本、改 JSON、推 Git 就完事了。
最后的一点小感慨#
整个自动化流程,说白了,就是给像我这样的 I 人一点点缓冲空间。
我非常尊重那些坚持手工审核友链的朋友
那是对自己博客节奏和边界的坚持,我完全理解。
但我也知道,有不少朋友可能跟我一样:
- 觉得对方的博客不错
- 想互相交换友链
- 却迟迟按不下那个“开口”的按钮
这个脚本解决不了我鼓起勇气去申请别人友链的问题。
但至少 如果你也是这样的 I 人,来我的博客交换友链时,你完全可以毫无心理负担
如果你想看完整的代码与改动,可以看这里:
👉 点击查看 ↗