Inpaint-web 前端缓存策略:Service Worker 与离线功能实现
你是否曾在使用网页应用时遇到网络不稳定导致模型加载失败?是否希望即使在断网情况下也能继续编辑图片?Inpaint-web 作为一款基于 WebGPU 和 WASM 的开源图像修复工具,通过精心设计的缓存策略解决了这些痛点。本文将深入解析其前端缓存架构,包括 LocalForage 本地存储方案、模型预加载机制以及潜在的 Service Worker 实现路径,帮助开发者构建更可靠的离线优先应用。
缓存架构概览
Inpaint-web 采用双层缓存架构:内存缓存用于临时数据处理,持久化存储负责模型文件和用户配置的长期保存。核心实现集中在 src/adapters/cache.ts 文件,通过 LocalForage 库提供的异步存储 API,实现了跨浏览器兼容的本地数据库功能。
// 核心缓存初始化代码 [src/adapters/cache.ts](https://link.gitcode.com/i/947203fa03cf5c708c51fe53b72366c9#L5-L7)
import localforage from 'localforage'
localforage.config({
name: 'modelCache', // 数据库名称
})
技术选型考量
项目选择 LocalForage 而非传统 localStorage 的原因在于:
- 支持二进制数据存储,适合处理 ONNX 模型文件
- 异步 API 设计,避免阻塞主线程影响 UI 响应
- 自动降级策略,在不支持 IndexedDB 的浏览器中回退到 WebSQL
模型缓存实现
三级缓存检查机制
Inpaint-web 的模型加载流程遵循本地优先原则,通过 src/adapters/cache.ts 中的 ensureModel 函数实现三级检查:
- 内存缓存:运行时已加载的模型直接使用
- 本地存储:检查 LocalForage 中是否存在缓存模型
- 网络请求:从 HuggingFace 仓库下载并缓存模型
// 模型加载优先级控制 [src/adapters/cache.ts](https://link.gitcode.com/i/947203fa03cf5c708c51fe53b72366c9#L63-L71)
export async function ensureModel(modelType: modelType) {
if (await modelExists(modelType)) {
return loadModel(modelType) // 优先使用本地缓存
}
const model = getModel(modelType)
const response = await fetch(model.url)
const buffer = await response.arrayBuffer()
await saveModel(modelType, buffer) // 下载后自动缓存
return buffer
}
模型下载与进度反馈
模型文件通常体积较大(数百 MB),src/adapters/cache.ts 中的 downloadModel 函数实现了带进度条的分块下载:
// 分块下载与进度更新 [src/adapters/cache.ts](https://link.gitcode.com/i/947203fa03cf5c708c51fe53b72366c9#L82-L115)
async function downloadFromUrl(url: string) {
console.log('start download from', url)
setDownloadProgress(0)
const response = await fetch(url)
const fullSize = response.headers.get('content-length')
const reader = response.body!.getReader()
const total: Uint8Array[] = []
let downloaded = 0
while (true) {
const { done, value } = await reader.read()
if (done) break
downloaded += value?.length || 0
total.push(value)
setDownloadProgress((downloaded / Number(fullSize)) * 100) // 实时进度更新
}
// 合并分块并保存
}
多模型管理策略
系统支持多种模型类型的缓存隔离,通过 modelType 参数区分:
// 模型类型定义 [src/adapters/cache.ts](https://link.gitcode.com/i/947203fa03cf5c708c51fe53b72366c9#L3)
export type modelType = 'inpaint' | 'superResolution'
当前支持的模型列表包括:
- 图像修复模型:migan-pipeline-v2(默认)
- 超分辨率模型:realesrgan-x4
图 1:模型下载进度条组件,通过缓存状态实时更新 UI
离线功能规划
Service Worker 集成路径
虽然当前代码库尚未实现 Service Worker,但基于项目架构可采用以下实现路径:
- 注册 Service Worker:在 index.html 中添加注册代码
- 缓存静态资源:在
install事件中缓存 HTML/CSS/JS 核心文件 - 运行时缓存:拦截网络请求,实现动态内容的缓存策略
// 建议的 Service Worker 注册代码(需添加到 [index.html](https://link.gitcode.com/i/3b850268dc0bc55debe2ff9ab65be2b6))
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => console.log('SW registered:', registration.scope))
.catch(err => console.log('SW registration failed:', err))
})
}
缓存策略矩阵
| 资源类型 | 缓存策略 | 优先级 | 更新机制 |
|---|---|---|---|
| 模型文件 | CacheFirst | 高 | 版本号控制 |
| 静态资源 | StaleWhileRevalidate | 中 | 哈希文件名 |
| 用户图片 | NetworkFirst | 低 | 会话级缓存 |
性能优化实践
内存管理
为避免大模型占用过多内存导致页面崩溃,src/adapters/cache.ts 实现了按需加载机制:
// 模型存在性检查 [src/adapters/cache.ts](https://link.gitcode.com/i/947203fa03cf5c708c51fe53b72366c9#L58-L61)
export async function modelExists(modelType: modelType) {
const model = await loadModel(modelType)
return model !== null && model !== undefined
}
缓存清理策略
虽然当前代码未实现自动清理,但可通过以下方式扩展:
- 监听
storage事件实现缓存过期策略 - 添加用户触发的清理按钮(建议实现到设置面板)
- 基于 LRU 算法淘汰不常用模型
实际应用场景
离线工作流
视频:断网状态下使用缓存模型进行图像修复
典型离线使用流程:
- 首次联网时自动缓存基础模型(约 300MB)
- 下载示例图片到本地(public/examples/)
- 断网后仍可使用缓存资源继续编辑
弱网环境优化
在网络不稳定时,src/adapters/cache.ts 中的备份 URL 机制保障下载可靠性:
// 双 URL 备份机制 [src/adapters/cache.ts](https://link.gitcode.com/i/947203fa03cf5c708c51fe53b72366c9#L27-L31)
{
name: 'migan-pipeline-v2',
url: 'https://huggingface.co/andraniksargsyan/migan/resolve/main/migan_pipeline_v2.onnx',
backupUrl: 'https://worker-share-proxy-01f5.lxfater.workers.dev/andraniksargsyan/migan/resolve/main/migan_pipeline_v2.onnx',
}
未来扩展方向
- Service Worker 集成:实现完全离线运行能力
- 缓存预热:后台预加载常用模型
- 差分更新:仅下载模型增量部分
- 云端同步:跨设备共享缓存配置
总结
Inpaint-web 通过 LocalForage 实现的缓存系统,在保证 Web 应用灵活性的同时,提供了接近原生应用的离线体验。核心代码 src/adapters/cache.ts 展示了如何平衡性能、兼容性和用户体验,为前端开发者提供了可复用的大型资源缓存方案。
建议开发者在实现类似功能时:
- 优先采用成熟的存储库而非原生 API
- 设计清晰的缓存失效机制
- 提供明确的加载状态反馈
- 考虑移动端存储限制进行适配
通过本文介绍的缓存策略,即使在网络不稳定的环境下,用户也能流畅使用 Inpaint-web 的核心功能,真正实现"一次加载,多次使用"的离线优先体验。
完整缓存实现代码:src/adapters/cache.ts
项目配置文件:package.json
示例图片资源:public/examples/
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




