Wardrobe 图片性能优化:ipx+sharp 响应式图片服务与 PWA 缓存策略完整指南
【免费下载链接】wardrobeYour clothes, extracted and organized with gpt-image.项目地址: https://gitcode.com/gh_mirrors/wardro/wardrobe
Wardrobe 是一个本地优先的 AI 衣橱图库应用:它能把衣服照片中的单品抠图提取并自动整理入库。由于页面上有成百上千张 AI 生成的图片,Wardrobe 用 ipx + sharp 搭建了响应式图片服务,再配合 PWA Service Worker 的三级缓存策略,让大量图片依然能秒开。本文带你完整拆解这套图片性能优化方案。
一、先搞懂整体架构:图片是怎么被加载的?
Wardrobe 的图片链路可以概括为三段式:
- 服务端变换:浏览器不直接请求原图,而是请求
/_ipx/...路径,由 ipx 动态裁剪/缩放/压缩后返回(底层由 sharp 提供高性能图像处理能力); - 前端按视口选图:
OptimizedImage组件根据屏幕宽度,从预设断点中挑选最合适的图片尺寸加载,避免手机加载 4K 原图; - PWA 缓存兜底:Service Worker 拦截所有图片请求,用「缓存优先 + 后台更新」策略,第二次访问几乎零等待。
二、服务端:ipx + sharp 构建响应式图片服务
2.1 用 Vite 插件挂载 /_ipx 路由
响应式图片服务的核心在 scripts/responsive-image-api.mjs,它是一个标准的 Vite 插件:
- 在
configResolved阶段用ipxFSStorage指定public/和dist/作为图片源目录,默认缓存时长 24 小时; - 通过
createIPXNodeServer生成处理函数,并在configureServer/configurePreviewServer中把/_ipx前缀的请求挂到中间件上——开发服务器和生产 preview 都能用同一套逻辑; - 在 vite.config.mjs 中一行
responsiveImageApi()即完成接入,对业务代码零侵入。
依赖方面,package.json 中只引入了ipx@^3.1.1与sharp@^0.34.5两个核心包,轻量且不绑定框架。
2.2 sharp 在导入流水线中的"重活"
sharp 不仅支撑图片变换,还承担了 AI 导入流水线里最耗性能的工作(见 scripts/import-job-api.mjs):
- 图片归一化:
normalizeImage用 sharp 自动旋转 + 统一 sRGB 色彩空间,消除手机拍摄图的 EXIF 方向问题; - 智能裁切:AI 视觉模型返回归一化边界框后,sharp 按坐标
extract裁出单品区域,并自动外扩 8% 的留白; - 抠图后处理:AI 生成带色键背景的商品图后,sharp 在像素级完成去背、羽化、溢色(chroma spill)清理,最后用
frameTransparentGarment把透明衣服重新排版到 1024×1024 透明画布居中——这些像素级操作全靠 sharp 的 raw buffer 直读直写,性能远快于纯 JS 方案。
💡 分工很清晰:sharp 负责入库前的"生产",ipx 负责展示时的"消费",两者配合让原图永远不必直接暴露给浏览器。
三、前端:OptimizedImage 组件与断点策略
所有图片都统一走 src/OptimizedImage.jsx 组件,它基于@unpic/react封装,几个关键设计:
- 断点可配置:默认断点
[160, 240, 320, 480, 640, 800, 960, 1280],业务侧可按场景覆盖。例如卡片缩略图用[120, 180, 240, 320, 480],而大图区用[320, 480, 640, 800, 1040, 1280](见 src/App.jsx); - 首屏图片走 priority:标记
priority的图片会eager加载 + 预连接,其余全部loading="lazy"+decoding="async",把带宽留给首屏; - 质量参数:统一以
quality: 80交给 ipx 做有损压缩,视觉无损的同时体积显著下降; - 智能降级:
data:、blob:、/api/前缀的图片不走 ipx,直接渲染<img>,避免动态内容被错误变换。
这套组件 + 断点方案,是「响应式图片」三件套(srcset、sizes、懒加载)的完整落地。
四、PWA 缓存策略:Service Worker 三级缓存
4.1 缓存注册
生产模式下 src/main.jsx 会注册 public/sw.js,配合 public/manifest.webmanifest(standalone 模式)让用户把 Wardrobe「安装」到桌面。
4.2 三层缓存设计
public/sw.js 里用两个命名缓存把资源分了级:
| 层级 | 缓存名 | 策略 | 说明 |
|---|---|---|---|
| Shell 缓存 | open-wardrobe-shell-v1 | 预缓存 + 导航兜底 | install 时预置/与 manifest,页面导航失败时离线可开 |
| 图片缓存 | wardrobe-images-v1 | 缓存优先 + 后台更新(stale-while-revalidate) | 只缓存/_ipx/请求且content-type为image/*的响应 |
| 过期清理 | — | LRU 上限 800 条 | trimImages在写入时自动淘汰最旧条目,防止存储爆满 |
图片请求的拦截逻辑(public/sw.js)非常典型:命中缓存就先返回缓存并在后台偷偷刷新,未命中则请求网络并顺手写入缓存——既有缓存的速度,又能拿到新图。
4.3 与 HTTP 缓存头协同
Service Worker 只是第二道防线,HTTP 层同样精细:
- 衣橱库图片(
/api/import/library/*)返回Cache-Control: public, max-age=31536000, immutable——文件名即哈希,一年强缓存; - 进行中的任务资产返回
no-store——正在生成/重试的图片绝不允许缓存错版本; /api/路径的请求在 Service Worker 中直接放行不拦截,避免动态 JSON 被误缓存。
五、总结:这套方案值得抄作业的地方
- ✅图片不直接上原图:ipx 统一变换入口
/_ipx,sharp 负责高性能底力,原图始终留在本地磁盘; - ✅组件化收口:一个
OptimizedImage组件统管断点、懒加载、质量,业务代码零心智负担; - ✅PWA 三级缓存:预缓存 Shell、图片 SWR 缓存、导航离线兜底,再加 800 条 LRU 上限控制存储;
- ✅缓存头与 SW 分工:HTTP 头管"能不能长缓存",Service Worker 管"离线还能不能看"。
对图片量大的本地应用来说,这套 ipx + sharp + Service Worker 的组合拳,就是性能与体验兼得的关键。
【免费下载链接】wardrobeYour clothes, extracted and organized with gpt-image.项目地址: https://gitcode.com/gh_mirrors/wardro/wardrobe
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考