评论区加载不出来?把 Twikoo 从 Vercel 搬回自己服务器
现象
博客的评论区一直在转圈,一直以为是「没人评论所以空的」。
直到有一天为了查别的问题去调评论接口,发现请求根本没回来:
curl -X POST https://xxx.vercel.app/ → 超时 |
第一步:先看 DNS,别急着改代码
nslookup xxx.vercel.app |
结果:
Addresses: 2a03:2880:f12c:183:face:b00c:0:25de |
face:b00c 是 Facebook 的 IPv6 特征段,31.13.x 也是 Facebook 的地址块。再查一个对照组:
nslookup vercel.com → 64.239.123.1 ✅ 正常 |
结论:***.vercel.app 整段被 DNS 污染**,解析结果全被指到 Facebook 的 IP 上,所以永远连不上。Vercel 本身没问题,vercel.com 是好的。
这也解释了为什么有些人抱怨「Vercel 上的服务国内打不开」——不是平台的问题,是域名被挡住了。
第二步:自定义域名能用,但有版本坑
我早先给评论服务绑过一个自定义域(twikoo.xxx.com,CNAME 到 Vercel 的 DNS),这个域名没被污染,200 正常响应。
但调接口返回:
{"code":1001,"message":"请更新 Twikoo 云函数至最新版本"} |
按字面意思,应该去升级后端。于是我把后端镜像从头到尾换了几个版本——升到最新还是 1001。
回头看源码才发现,这句文案是误导的:
// @twikoojs/common |
1001 的真实含义是「事件不存在」。
这就对上了:前端加载的是 1.6.x,发的是 GET_COMMENTS 事件;后端早就是 2.x,事件名变了,直接不认。而提示文案还留在旧版本那句话上。
验证方法:换成不涉及事件名的接口试试:
GET_CONFIG → 正常返回配置 |
配置能读、数据能读,只有那一个事件不通——根本不是版本太旧,是前后端事件名对不上。
第三步:干脆搬回自己机器
既然域名被污染、版本又纠缠,索性不再依赖 Vercel。自己的服务器上跑一个容器就行:
docker run -d --name twikoo \ |
几个要点:
- **只监听
127.0.0.1**,公网访问一律走 nginx 反代 - 数据库连接串放在
--env-file里,文件权限600,不要写在命令行(会进 shell history) - 数据库还是用原来的 MongoDB Atlas,历史评论不用迁,连上就能读
/root/twikoo.env:
MONGODB_URI=mongodb+srv://用户:密码@集群/?retryWrites=true&w=majority |
第四步:nginx 反代到一个路径
不想再折腾子域名和证书,直接挂在主域名的路径下:
location ^~ /api/twikoo { |
rewrite ... break 那行是关键:容器的接口在根路径 / 上,请求进来是 /api/twikoo,必须把前缀削掉再转发,否则容器收到 /api/twikoo 会 404。
博客配置改成:
twikoo: |
好处是:不用动 DNS、不用单独申请证书,主域名有什么配置它就用什么。
第五步:前端也得是 2.x
后端换好了,前端还停在 1.6.x,照样不通。但直接改版本号会撞墙:
https://cdn.staticfile.org/twikoo/2.0.17/twikoo.all.min.js → 404 |
国内 CDN 只同步到 1.6.31,jsdelivr 这边又连不上。绕开的办法是从国内 npm 镜像把包下下来,放到自己站点里:
curl -o source/js/twikoo.all.min.js \ |
然后在主题配置里覆盖这个脚本的地址(Butterfly 支持逐个插件指定 URL):
CDN: |
顺带的好处:评论系统不再依赖任何外部 CDN,外部 CDN 出问题、域名被墙,跟我没关系了。
结果
| 项目 | 之前 | 现在 |
|---|---|---|
| 评论接口 | *.vercel.app,国内不通 |
自己的域名/api/twikoo |
| 前端脚本 | 第三方 CDN 1.6.x | 本站托管 2.0.x |
| 数据 | Atlas | Atlas(不变,直接沿用) |
| 部署平台 | Vercel | 自己的 Docker |
历史评论一条没丢——数据一直在数据库里,之前只是「接口调不通」,不是「数据没了」。
复盘
这次真正花时间的不是部署,是被错误提示带偏。「请更新云函数」这句话让我在后端版本上兜了好几圈,而真实原因(事件名变了)藏在源码的一个常量定义里。
遇到报错,尤其是第三方封装过的报错,先去查错误码的真实定义,别信文案。
