一个 issue 提醒了我:README 里的截图,国内访问 GitHub 时全挂了
周末正准备摸鱼,GitHub 上连续弹了几个通知,是同一个小开源项目的 issue。点开一看,标题都差不多:“README 里的图片加载不出来”“演示截图全是裂的”,对方还很贴心地贴了截图——果然,本该是架构图和效果对比的地方,齐刷刷一排裂图占位符。
我第一反应是:不至于吧,我这边打开好好的。于是随手回了句“可能是网络问题,刷新试试”。结果第二天、第三天,类似的 issue 又冒出来两个,我才意识到这事儿不能再甩锅给“网络”,得自己查一查。这篇就把这次排查的过程和最后怎么解决的,按时间线记下来。
一、我先怀疑对方网络,结果被现实教育
我让其中一位反馈者做了件最简单的事:在裂图上右键,复制图片地址发给我。拿到链接一看,域名是 camo.githubusercontent.com,后面跟着一长串参数。我又让他直接在新标签页里打开这个地址,结果是转了半天圈,最后超时。
为了复现,我用手机热点(相当于换了个网络环境)打开项目主页,这回轮到我傻眼了:文字和代码都正常,图片一张张地慢慢崩掉,跟 issue 里描述的一模一样。我又用 curl 单独测了下那张图:
curl -I -o /dev/null -w "状态:%{http_code} 总耗时:%{time_total}s\n" "图片地址"
在我的常用网络下是 200、很快;一换到热点,就卡在连接阶段,最后返回 000。到这一步我才承认:不是人家网络差,是我的 README 图片,在国内很多网络环境下本来就打不开。
二、顺手把 GitHub README 的图片机制搞明白了
带着疑问去查了一圈,才算弄明白 README 里的图到底是怎么加载的,这里给和我一样一知半解的同学捋一下:
- 图片如果放在仓库里、用相对路径引用(比如
images/a.png),GitHub 网页渲染时,最终会把它指向 raw 域名,或者走图片代理; - 如果直接贴
raw.githubusercontent.com的链接,浏览器就老老实实去请求 raw; - 如果是第三方外链(你自己服务器或某个图床的图),GitHub 出于安全考虑,会让它统一经过 Camo 这个图片代理,你右键看到的就是
camo.githubusercontent.com开头的签名地址。
问题就出在这几个域名上。raw.githubusercontent.com 和 camo.githubusercontent.com 在国内的访问都不稳定,经常出现解析失败或连接被重置;README 里图一多,连接串行排队,就成了“一直转圈最后全裂”。也就是说,只要图片还压在这两个域名上,国内能不能看到,基本是看运气。
这其实跟我之前写博客时遇到的“裂图”是同一类毛病,图源不稳定、或者被中间环节卡住,图就挂了。我在《博客配图为什么总会「裂」?聊聊图床的坑,和我现在的自动化配图流程》里详细聊过:https://www.cnblogs.com/dogma/p/23002935 。
三、几种方案我都试了试,说下真实感受
搞清楚原因后,我把能想到的办法都试了一遍,感受比较主观,供参考:
- 维持现状,图放仓库里用相对路径:最省事,但仓库越塞越大,
clone越来越慢,而且网页上照样走 raw / camo,国内该裂还是裂,治标不治本; - 换成 jsDelivr 引仓库文件:写法是
cdn.jsdelivr.net/gh/用户名/仓库@版本/路径,国内访问确实稳了不少。但它对单文件大小、仓库总容量有限制,而且更新图片后有 CDN 缓存,不手动 purge 的话,老截图能挂好几天,对我这种三天两头改演示图的人来说有点折腾; - 自建对象存储再套 CDN:最可控,但要自己去开通、配置、配压缩和防盗链,为一个小项目搞这套,我实在提不起劲;
- 把展示图放到独立图床:上传后直接拿 https 链接往 README 里填,国内访问快,更新截图还能同名覆盖、链接不变,不用回头改文档,对个人项目来说性价比最高。
四、最后固定下来的一套做法
折腾完,我现在会把 README 里的图分两类:
- 要跟着代码版本走的图(比如教程里的输入输出样本),数量少、体积小,留在仓库里;
- 纯展示用的图(logo、演示截图、架构图、效果对比),从仓库里搬出来,统一放到一个稳定的图源,README 里直接引用 https 链接。
挑图源我主要看四点:支持 https、国内打开快、域名固定不常变、能同名覆盖。另外坚持给每张图写 alt,关键信息不只用图来表达——万一图真挂了,读者好歹知道那里本该是什么。
老 README 里的图,我是用一条正则把图片链接批量抽出来,转存到图源之后再批量替换回去的,没一张张手改:
!\[.*?\]\((https?://[^)]+)\)
我自己图省事,展示图统一放在图床小镇,截图改好了重新传一遍、链接不变,国内小伙伴那边也能正常显示;不过这纯粹是我个人的懒办法,jsDelivr、自建 OSS+CDN 都是可行的路子,大家按项目大小和自己的精力来选,没必要照搬我的。 之前把一篇文章发到公众号、知乎和博客时,我也是靠“一处上传、多处引用”省掉了重复传图,思路是相通的:https://www.cnblogs.com/dogma/p/23068858 。
五、一个简单的收尾自检
弄完之后我给自己列了个小清单,每次改 README 前过一遍:
- 换个网络(或让国内的朋友)实际打开 README 看一眼;
- 图片全用 https,不放 http 外链;
- 大图先压缩,别把好几 MB 的截图直接塞进仓库;
- 每张图都写
alt; - 原本用 raw 直链的展示图,换成 CDN 或图床链接;
- 顺手确认下
clone下来的仓库体积还能接受。
说实话,开源项目的 README 就是给人的第一印象,内容写得再用心,一打开图片全是裂的,对方大概率就关掉了。把展示用的图源和仓库解耦、换成国内稳定的链接,这类 issue 之后基本就没再出现过,也算是花一个周末换来了长期清净。
浙公网安备 33010602011771号