先说清楚,这篇不是教程。怎么接 R2、怎么写那段标签匹配的 JS,这些我打算以后单独整理一篇,把踩过的坑按步骤写明白。这篇更像是一个阶段性记录——画廊页的图片数量前阵子悄悄越过了五千,我在整理的时候突然意识到,有些问题跟"图床选谁"关系不大,是数量堆上来之后才浮出水面的。
一开始只是想放几十张
画廊这个菜单页,最初的想法特别朴素。博客侧边栏里挂个入口,点进去能看到一些我自己拍的、或者觉得好看的图,排成一格一格的,鼠标放上去有点反馈,就够了。
第一批大概四十来张。我手动改了个 HTML,一个 <img> 一个 <img> 地往下贴,路径指向当时随便找的一个图床。那会儿完全没想过"以后会怎样",就觉得反正图不多,改起来也快。
后来事情开始不受控。有朋友拍了照片直接甩给我,说"你这画廊挺好看,给我也放几张";有群友发来一堆截图,问能不能归档;我自己也陆陆续续往里丢一些随手存的东西。慢慢地,我打开那个 HTML 文件,往下滚要滚好几屏,再后来编辑器开始卡。
到某个节点,我意识到不能再手写 <img> 了。那次具体是多少张我忘了,大概两三百。也就是那个时候,我才开始认真考虑存储和索引这两件事。
存储最后选了 R2
选 R2 的原因没什么戏剧性。CF 的 R2 有免费额度,出站流量不计费,对一个纯展示、访问量也不大的个人画廊来说,成本几乎可以忽略。我在 CF 后台开了个桶,绑了个子域名,把图片全迁过去,配好缓存,这部分其实相当顺。
真正麻烦的是迁完之后的那堆文件。别人给我的图,文件名千奇百怪。有叫 IMG_20230415_183022.jpg 的,有叫 微信图片_2023xxxx.jpg 的,有直接一串哈希的,还有同一个文件被不同的人发了两遍、名字完全不一样、但内容一模一样的。五千张图里,我估计至少有两三百张是重复的,只是我当时没精力去查。
R2 本身没给我添什么乱。它安安静静地存着,我按路径去取,它就返回。五千张图放在桶里,和三十张图放在桶里,从存储的角度看没区别。所以我前面说,图床是最不用操心的一环——至少在我不做任何图片处理、不搞动态裁剪的前提下,它确实没拖后腿。
本地 JS 标签匹配,省了后端也埋了雷
画廊页真正的逻辑在浏览器里。我没有数据库,也没有后端接口。每张图的路径、标题、几个标签,全都写在本地的一个 JS 数据文件里,格式大概就是数组套对象。页面加载之后,脚本读这个数组,根据 URL 里的查询参数或者页面上的按钮,把匹配的图筛出来渲染。
好处很明显:不要服务器,不要数据库,部署的时候连构建步骤都能省。坏处也很明显,就是所有的索引数据都在前端,五千张图的元数据堆在一个 JS 文件里,这个文件已经不小了。
我记得有一次随手看了一眼 Network 面板,那个数据文件压缩前大概有几百 KB。对宽带来说不算什么,但对一个只想瞄一眼画廊的人来说,他得先把这几百 KB 拉下来,才能开始看图。如果这个人还在用手机流量,那我多少有点过意不去。
标签匹配本身倒没出过什么大问题,就是纯数组过滤。真正花时间的是标签本身。五千张图,每张都要打几个标签,这件事我拖了很久,到现在也没打完。早期打标签的时候我还挺认真,会想"这个算风景还是算城市",后来就变成了"先打上再说"。所以你如果现在去翻,会发现标签体系有点漂移,早期和后期的口径不完全一致。
五千这个数字带来的变化
数量过了五千之后,有几件事开始变得明显。
第一个是首屏。图片一多,就算做了懒加载,第一次进页面的时候还是会有那么一下下的空白。我自己在本地测的时候没感觉,后来用手机 4G 打开,才意识到那个等待是真实存在的。
第二个是找图。以前图少,我大概记得某张图在哪个位置。现在不行了,我只能靠标签和搜索。可标签是我自己打的,有时候我记得"那张有海边的图",但当时打的标签可能是"蓝色"和"夏天",搜"海"反而搜不到。这种自己坑自己的事发生过不止一次。
第三个是重复和命名。前阵子我下定决心清一遍,写了个很粗糙的脚本,按文件大小和哈希粗略分组,人工过了一遍。清出来几十张重复的,还有一批名字和内容完全对不上的——比如一张叫 cat.jpg 的图,点开是张夜景。
第四个是心理上的。五千张图摆在那儿,会有一种"我得对它负责"的感觉。这些图很多是别人给的,人家给的时候可能就一句"放你画廊吧",但真放进去之后,路径不能随便改,改了别人的链接就断了;文件不能随便删,删了可能人家还留着旧地址。这个负担是之前放四十张图的时候完全没想到的。
一些目前的做法
我现在做的事情其实都很土。
图片统一转成 webp,太大的先压一道,控制在合理体积。路径按年份和月份分目录,文件名尽量保留原样,实在没法看的才重命名,重命名的时候会在数据文件里留个记录。标签这块,我放弃了追求完美体系,改成"够用就行",常用的标签控制在几十个以内,剩下的靠标题里的关键词兜底。
那段本地 JS 我没动大结构,只是把数据文件拆了一下,按年份拆成几个,页面根据当前筛选条件决定加载哪几个。这样一来,默认打开的时候不用把五千张图的元数据全拉下来。这个改动不大,但体感上好了不少。
至于 R2,我还是没动它。它继续安安静静地存着,我继续按月付那点几乎可以忽略的费用。有时候我会想,如果哪天图片数量再翻一倍,会不会有新的问题冒出来。大概率会。但至少现在,我大概知道该往哪个方向去看。
这篇就先记到这儿。教程那篇我欠着,等我把标签体系再捋一遍,把那段 JS 整理得能见人了再写。