MoGallery-图片滚动优化

701 字
4 分钟
MoGallery-图片滚动优化

一直发现gallery页面上下滚动时,时不时出现部分区域空白的情况,但一直排查不到哪里的问题。

排查点:

  • F12无任何网络请求,排查了网络请求带来的影响
  • 对比aflimory图片滚动加载逻辑,可以同样看作静态页面

问题所在:

  • 之前图片上传逻辑中,有开启了压缩选项的话,缩略图字段就共用了原图url字段,但压缩后的照片依然存在较大的体积,带来的性能的问题

AI总结#

问题不是”照片没加载”,而是图片解码。上传接口在”压缩原图”模式下把压缩后的原图直接当缩略图(thumbnailUrl = url),导致 29 张最新上传的照片以 12~22MP 的分辨率进入画廊网格:

  • 一张 4096×3072 的图,解码后的位图约 50MB(4096 × 3072 × 4 字节),单次解码 300~400ms 纯 CPU 开销;
  • 缓存只免下载,不免解码。虚拟列表把滚出视口的卡片卸载,滚回来重新挂载 <img> 就要重新解码——9 秒滚动里发生了约 1500 次解码;
  • decoding="async" 的行为是”先画一帧没有图的空白,解码完再补”——这正是”成片区域空白 + 卡顿、但 F12 无请求”的来源。

修复分两步:

  1. 堵源头:hono/photos.ts 上传接口不再在压缩模式下复用原图当缩略图,无论什么模式一律生成独立的 800px AVIF 缩略图(每张多占 ~30-170KB 存储)。三端(Web/Flutter/Desktop)上传全部汇入这一个服务端接口,客户端零改动。
  2. 补存量:scripts/backfill-thumbnails.ts(默认 dry-run,--apply 才写入)为 29 张存量照片生成缩略图上传到 R2 同目录 thumb-*.avif 并更新数据库,原图 232KB3.8MB → 缩略图 26170KB。原图不动、可回滚,以后也可当巡检工具复查。

此前对 masonic 布局层的重写(把已知的照片宽高预先种进 positioner)解决的是另一半问题——拖滚动条远跳时无上限隐藏渲染批次导致的冻结、首帧列数跳变;压测确认 JS/渲染层不是瓶颈(JS 总耗时 749ms,渲染断层≈0)。

修复前后压测对比(同机同脚本,headless Chrome + Performance trace):

指标修复前修复后
≥2000px 的大图解码29 张0
主线程长任务(≥50ms)18 次 / 累计 4782ms / 最长 732ms3 次 / 185ms / 最长 75ms
单次图片解码最长383ms15ms
栅格化耗时2133ms11ms
视口零卡片采样(渲染断层)20(视口内最少 12 个卡片)

一句话总结:文件小 ≠ 像素少。压缩解决的是字节,缩略图解决的是像素,两者不能互相替代;判断图片性能问题看 MP,不看 KB。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

MoGallery-图片滚动优化
https://shaio.top/posts/dev/mogallery-图片滚动优化/
作者
沙海
发布于
2026-07-19
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
沙海
Hello, I'm Shai.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
84
分类
15
标签
48
总字数
67,035
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.12.2
文章许可
CC BY-NC-SA 4.0

文章目录