当前位置:首页 > 行业动态 > 正文

h5实现网络缓存图片

通过Service Worker缓存图片:注册worker后,在install事件中缓存图片资源,拦截fetch请求时优先返回缓存,未命中则获取网络资源并缓存

H5实现网络缓存图片的核心技术与实践指南

HTML5缓存机制

HTML5提供了多种客户端缓存方案,其中与网络图片缓存相关的核心技术包括:

  1. Application Cache(应用缓存):通过manifest文件预定义缓存资源
  2. Service Worker:通过JavaScript实现异步缓存控制
  3. LocalStorage/IndexedDB:键值对存储(适合少量数据)
  4. Cache API:配合Service Worker使用的缓存接口
缓存方案 支持浏览器 离线能力 更新控制 存储容量
Application Cache IE10+/Chrome/Firefox 完全离线 自动更新 约5MB
Service Worker IE11+/Chrome/Firefox/Safari 完全离线 手动控制 无限制
LocalStorage 全平台现代浏览器 5-10MB
IndexedDB 全平台现代浏览器 500MB+

Application Cache实现图片缓存

创建缓存清单文件(manifest)

CACHE MANIFEST
# v1.0 2023-08-01
CACHE:
/images/logo.png
/images/banner.jpg
/css/style.css
/js/app.js
NETWORK: 

HTML引用manifest文件

<!DOCTYPE html>
<html lang="zh-CN" manifest="cache.manifest">
<head>
    <meta charset="UTF-8">图片缓存示例</title>
</head>
<body>
    <img src="images/logo.png" alt="Logo">
    <img src="images/banner.jpg" alt="Banner">
</body>
</html>

工作原理说明

  • 首次加载时,浏览器按manifest文件缓存资源
  • 后续访问直接使用本地缓存资源
  • 更新manifest版本号可触发缓存刷新

Service Worker实现智能缓存

注册Service Worker

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js')
        .then(reg => console.log('SW注册成功:', reg))
        .catch(err => console.error('SW注册失败:', err));
}

Service Worker核心代码(sw.js)

const CACHE_NAME = 'image-cache-v1';
const IMAGE_URLS = [
    '/images/logo.png',
    '/images/banner.jpg'
];
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => cache.addAll(IMAGE_URLS))
    );
});
self.addEventListener('fetch', event => {
    if (event.request.url.endsWith('.png') || event.request.url.endsWith('.jpg')) {
        event.respondWith(
            caches.match(event.request)
                .then(response => response || fetch(event.request))
        );
    }
});

缓存策略对比表

策略类型 适用场景 更新机制 性能表现
Cache-First 静态资源(图片/CSS/JS) 手动版本控制 最佳加载速度
Network-First 动态数据(API响应) 实时获取 数据及时性高
Stale-While-Revalidate 平衡型需求 后台静默更新 兼顾速度与时效

缓存更新与版本管理

Application Cache更新流程

  • 修改manifest文件内容(如版本号)
  • 浏览器检测到manifest变化后重新下载资源
  • 旧缓存保留直到新缓存完全可用

Service Worker更新策略

// sw.js中监听update事件
self.addEventListener('updatefound', event => {
    const newWorker = event.newRegistration;
    newWorker.onupdatefound = function() {
        if (navigator.serviceWorker.controller) {
            // 有旧版本在运行,提示用户刷新
            console.log('发现新版本,请刷新页面');
        }
    };
});

强制刷新缓存方法

// 通过重新注册Service Worker实现强制更新
navigator.serviceWorker.getRegistration().then(reg => {
    if (reg) {
        reg.unregister().then(() => {
            window.location.reload();
        });
    }
});

性能优化与异常处理

缓存容量控制

// 使用IndexedDB存储大文件路径
const db = new Dexie('ImageCacheDB');
db.version(1).stores({
    images: '++id,url,timestamp'
});
// 缓存前检查存储空间
navigator.storage.estimate().then(est => {
    if (est.usage < est.quota 50  1024  1024) { // 剩余50MB空间
        cache.add(url);
    } else {
        console.warn('存储空间不足,跳过缓存');
    }
});

缓存失效处理机制

fetch(url)
    .then(response => {
        if (!response.ok) throw new Error('网络响应异常');
        return caches.open(CACHE_NAME).then(cache => {
            cache.put(url, response.clone());
            return response;
        });
    })
    .catch(err => {
        return caches.match(url).then(cachedResponse => {
            if (cachedResponse) return cachedResponse;
            throw new Error('网络故障且无缓存');
        });
    });

跨域缓存解决方案

<!-设置CORS响应头 -->
Access-Control-Allow-Origin: 
Access-Control-Max-Age: 3600
// Service Worker处理跨域请求
event.respondWith(
    fetch(event.request).then(response => {
        // 克隆可跨域的响应对象
        return response.clone();
    }).catch(() => caches.match(event.request))
);

实战案例分析

案例:电商商品图片缓存优化

  1. 需求分析

    • 商品列表页大量图片需要快速加载
    • 用户频繁切换分类时避免重复加载
    • 支持离线查看最近浏览的商品
  2. 实施方案

    • 使用Service Worker实现三级缓存:
      • L1:内存缓存(当前会话)
      • L2:Service Worker缓存(会话间持久)
      • L3:IndexedDB存储(长期保存)
    • 采用Stale-While-Revalidate策略:
      • 优先显示缓存图片(L1->L2->L3)
      • 后台静默更新最新图片版本
  3. 效果对比
    | 指标 | 优化前 | 优化后 | 提升幅度 |
    |————–|————–|————–|———-|
    | 首屏加载时间 | 3.2s | 0.8s | 75% |
    | 图片重载率 | 62% | 9% | 85% |
    | 离线可用率 | 0% | 92% | |

常见问题与解决方案

Q1:缓存图片导致页面无法获取最新内容?

解决方案

  1. 为缓存资源添加版本参数:logo.png?v=1.0.1
  2. 使用Service Worker的updatefound事件通知用户刷新:
    self.addEventListener('updatefound', event => {
        clients.claim().then(() => {
            clients.matchAll({type: 'window'}).forEach(client => {
                client.navigate(client.url); // 强制刷新页面
            });
        });
    });
  3. 配置服务器返回强缓存失效头部:Cache-Control: no-cache

Q2:如何判断图片是否已缓存?

检测方法

async function checkCache(url) {
    try {
        const cache = await caches.open('image-cache-v1');
        const match = await cache.match(url);
        return match ? '已缓存' : '未缓存';
    } catch(e) {
        return '检测失败';
    }
}
0