Featured image of post 画廊里塞进五千张鸣潮角色图之后,我才发现图床是最不用操心的一环

画廊里塞进五千张鸣潮角色图之后,我才发现图床是最不用操心的一环

给博客做了个画廊页,本来只想放点自己的图,结果陆陆续续被塞进五千多张鸣潮角色图,大半是别人分享的,存储扔在 CF 的 R2 上,标签匹配全靠本地一段 JS。这篇不是教程,就是记录一下这个数字涨上来之后,哪些地方开始不对劲。

先说清楚,这篇不是教程。怎么接 R2、怎么写那段标签匹配的 JS,这些我打算以后单独整理一篇,把踩过的坑按步骤写明白。这篇更像是一个阶段性记录——画廊页的图片数量前阵子悄悄越过了五千,而且清一色全是鸣潮的角色图,我在整理的时候突然意识到,有些问题跟"图床选谁"关系不大,是数量堆上来之后才浮出水面的。

一开始只是想放几十张

画廊这个菜单页,最初的想法特别朴素。博客侧边栏里挂个入口,点进去能看到一些我自己拍的、或者觉得好看的图,排成一格一格的,鼠标放上去有点反馈,就够了。

第一批大概四十来张,里面还有不少是我自己截的风景。后来玩鸣潮玩得多了,开始往里丢角色图,今汐的、长离的、守岸人的,一张一张存。再后来就彻底跑偏了,画廊里几乎找不到非鸣潮的图了。

事情真正不受控是从别人开始给我发图起。有群友拍了一堆角色截图直接甩过来,说"你这画廊挺好看,帮我归档一下";有人把存了好几年的同人图打包发我,问能不能放进去;我自己也陆陆续续从各处存。慢慢地,我打开那个 HTML 文件,往下滚要滚好几屏,再后来编辑器开始卡。

到某个节点,我意识到不能再手写 <img> 了。那次具体是多少张我忘了,大概两三百。也就是那个时候,我才开始认真考虑存储和索引这两件事。

存储最后选了 R2

选 R2 的原因没什么戏剧性。CF 的 R2 有免费额度,出站流量不计费,对一个纯展示、访问量也不大的个人画廊来说,成本几乎可以忽略。我在 CF 后台开了个桶,绑了个子域名,把图片全迁过去,配好缓存,这部分其实相当顺。

真正麻烦的是迁完之后的那堆文件。五千多张鸣潮角色图,大半是别人分享的,文件名千奇百怪。有规规矩矩叫 今汐.png 的,有叫 Jinhsi_5star.jpg 的,有叫 微信图片_2023xxxx.jpg 的,有直接一串哈希的,还有同一个角色同一张图被不同的人发了两遍、名字完全不一样、但内容一模一样的。五千张图里,我估计至少有两三百张是重复的,只是我当时没精力去查。

R2 本身没给我添什么乱。它安安静静地存着,我按路径去取,它就返回。五千张图放在桶里,和三十张图放在桶里,从存储的角度看没区别。所以我前面说,图床是最不用操心的一环——至少在我不做任何图片处理、不搞动态裁剪的前提下,它确实没拖后腿。

本地 JS 标签匹配,省了后端也埋了雷

画廊页真正的逻辑在浏览器里。我没有数据库,也没有后端接口。每张图的路径、标题、几个标签,全都写在本地的一个 JS 数据文件里,格式大概就是数组套对象。页面加载之后,脚本读这个数组,根据 URL 里的查询参数或者页面上的按钮,把匹配的图筛出来渲染。

好处很明显:不要服务器,不要数据库,部署的时候连构建步骤都能省。坏处也很明显,就是所有的索引数据都在前端,五千张图的元数据堆在一个 JS 文件里,这个文件已经不小了。

我记得有一次随手看了一眼 Network 面板,那个数据文件压缩前大概有几百 KB。对宽带来说不算什么,但对一个只想瞄一眼画廊的人来说,他得先把这几百 KB 拉下来,才能开始看图。如果这个人还在用手机流量,那我多少有点过意不去。

标签匹配本身倒没出过什么大问题,就是纯数组过滤。真正花时间的是标签本身。鸣潮角色的标签体系看着简单,其实挺琐碎:角色名一个维度,属性一个维度,稀有度一个维度,武器类型一个维度,再分官方图、同人图、截图、表情包,同人图还牵扯到画师。五千张图,每张都要打几个标签,这件事我拖了很久,到现在也没打完。早期打标签的时候我还挺认真,会想"这张算同人还是算二创截图",后来就变成了"先打上再说"。所以你如果现在去翻,会发现标签体系有点漂移,早期和后期的口径不完全一致,有的角色名写中文,有的写英文,还有的干脆只写了拼音。

五千这个数字带来的变化

数量过了五千之后,有几件事开始变得明显。

第一个是首屏。图片一多,就算做了懒加载,第一次进页面的时候还是会有那么一下下的空白。我自己在本地测的时候没感觉,后来用手机 4G 打开,才意识到那个等待是真实存在的。

第二个是找图。以前图少,我大概记得某张图在哪个位置。现在不行了,我只能靠标签和搜索。可标签是我自己打的,有时候我记得"那张长离在雨里的图",但当时打的标签可能是"热熔"和"夏天",搜"雨"反而搜不到。这种自己坑自己的事发生过不止一次。更麻烦的是别人分享的图,发过来的时候什么信息都没有,我得自己认角色、认属性,认不出来的就先挂个"待定",挂到现在"待定"里还躺着一堆。

第三个是重复和命名。前阵子我下定决心清一遍,写了个很粗糙的脚本,按文件大小和哈希粗略分组,人工过了一遍。清出来几十张重复的,还有一批名字和内容完全对不上的——比如一张叫 jinhsi.jpg 的图,点开是张忌炎的立绘,估计是分享的人自己存串了。

第四个是心理上的。五千张鸣潮图摆在那儿,会有一种"我得对它负责"的感觉。这些图很多是别人给的,人家给的时候可能就一句"放你画廊吧",但真放进去之后,路径不能随便改,改了别人的链接就断了;文件不能随便删,删了可能人家还留着旧地址。尤其是同人图,很多是画师辛苦画的,分享来分享去画师名字早就丢了,我有时候看着一张图不知道作者是谁,心里会有点别扭。这个负担是之前放四十张图的时候完全没想到的。

一些目前的做法

我现在做的事情其实都很土。

图片统一转成 webp,太大的先压一道,控制在合理体积。路径按角色分目录,角色下面再按月份或者来源简单分一层,文件名尽量保留原样,实在没法看的才重命名,重命名的时候会在数据文件里留个记录。标签这块,我放弃了追求完美体系,改成"够用就行",角色名和属性是必打的,剩下的靠标题里的关键词兜底。碰到能认出来的同人图,我会尽量把画师名记在标题或者标签里,认不出来的就在备注里写一句"来源不明"。

那段本地 JS 我没动大结构,只是把数据文件拆了一下,按角色或者按批次拆成几个,页面根据当前筛选条件决定加载哪几个。这样一来,默认打开的时候不用把五千张图的元数据全拉下来。这个改动不大,但体感上好了不少。

至于 R2,我还是没动它。它继续安安静静地存着,我继续按月付那点几乎可以忽略的费用。有时候我会想,如果哪天图片数量再翻一倍,会不会有新的问题冒出来。大概率会。但至少现在,我大概知道该往哪个方向去看。

这篇就先记到这儿。教程那篇我欠着,等我把标签体系再捋一遍,把那段 JS 整理得能见人了再写。

使用 Hugo 构建
主题 Stack 由 Jimmy 设计
昭鸢笺 · 笺册渐启…