响应式图片在H5中实现移动端离线缓存,核心是主动拦截请求、下载并用IndexedDB存储二进制图片,配合Service Worker按设备特征(dpr/format)生成唯一键查缓存,fallback至基础尺寸保证可用性。

响应式图片在 H5 中实现移动端离线缓存,核心不是“让 img 标签自动缓存”,而是主动拦截、下载、存储并按需加载。浏览器原生的 <picture> 或 srcset 只负责根据屏幕条件选择资源 URL,不参与缓存控制;真正实现离线可用,必须结合前端存储机制与请求拦截策略。
用 IndexedDB 存储二进制图片(推荐)
localStorage 仅支持字符串,无法高效存取图片这类二进制资源;强行转 base64 会膨胀约 33%,读写慢且易触发存储上限。IndexedDB 是当前最实用的选择:
- 直接存取 Blob / ArrayBuffer,无编码开销,读写性能好
- 支持事务、索引和批量操作,适合管理多尺寸图片(如 1x/2x/webp)
- 主流安卓 WebView(4.4+)、iOS Safari(10.3+)、Chrome/Firefox 全面支持
- 示例逻辑:获取响应 →
res.arrayBuffer()→db.transaction(...).objectStore('images').put(buffer, url)
配合 Service Worker 拦截响应式请求
当页面使用 srcset 或 <source media="..." srcset="..."> 时,浏览器会根据设备像素比、宽度等发出多个资源请求(如 logo@2x.jpg、logo.webp)。你需要在 Service Worker 的 fetch 事件中统一拦截:
- 判断请求 URL 是否为图片(如匹配
/\.(png|jpe?g|webp|avif)$/i) - 优先查 Cache Storage(预缓存关键图)或 IndexedDB(按需缓存)
- 命中则构造
Response返回;未命中则 fetch 网络,成功后存入 IndexedDB 并返回 - 这样无论用户是 WiFi 还是离线,
<img srcset="...">都能从本地加载对应尺寸资源
适配响应式场景的缓存键设计
同一张图的不同尺寸/格式本质是不同资源,不能共用一个 key。建议按“URL + 设备特征”组合生成唯一键:
- 基础键:图片原始 URL(如
https://cdn.com/logo.png) - 增强键:拼接设备信息,例如
https://cdn.com/logo.png#dpr=2&format=webp,或哈希化处理sha256(url + dpr + format) - 在 JS 加载逻辑中,先检测
window.devicePixelRatio和document.createElement('canvas').toDataURL('image/webp')判断 webp 支持,再决定请求哪个变体并查对应缓存
降级与清理策略要务实
移动端存储空间有限,不能无限制缓存:
- 设置总容量上限(如 50MB),定期用
IDBKeyRange.bound扫描旧记录按时间或访问频次清理 - 对非关键图(如轮播图、广告图)采用“内存缓存 + localStorage 记录状态”轻量方案,避免挤占 IndexedDB
- 离线时若某尺寸图缺失,可 fallback 到基础尺寸(如只存 1x jpg,无 webp 时也显示 jpg),保证功能可用而非体验完美


















