AI生成海报H5后,我补了缓存

3 阅读4分钟

结论先放在前面:活动海报 H5 生成后,如果用户会反复改文案、切模板、返回预览,性能优化的重点是按输入内容缓存生成结果,并给模板资源设置长期缓存。只缓存整页,收益很有限。我拿一个周末活动页跑了一轮小基准,搭页面很快,后手处理缓存却更考验判断。

这个 H5 的流程很短:选模板、填标题、上传主图、生成预览。短流程容易制造错觉,仿佛请求也很少。可运营同学做一张海报,平均会改三次标题、来回比较两个模板,同一组合常被打开两三遍。生成接口每次都重跑,等待和流量便一起累积。

我怎么测

我用 Chrome DevTools 的 Fast 4G、4 倍 CPU 降速,准备 5 个模板和 7 组有效输入,连续点了 20 次预览。冷启动前清空站点存储,重复打开阶段保留缓存。数字只代表这组小样本,方便比较策略:

方案20次生成请求传输量重复预览中位耗时
无业务缓存2018.6 MB2.42 s
仅缓存模板资源2010.8 MB1.71 s
模板缓存加内容指纹74.3 MB0.79 s

静态资源缓存能改善加载,却拦不住重复生成。决定性变化来自内容指纹:模板、模板版本、文案、图片摘要和用户作用域都一致,才复用已有结果。

第一轮结果差点被我测歪:DevTools 的 Disable cache 还勾着,静态资源方案自然看不出收益;取消后又发现 Service Worker 没完成激活,首个样本仍走网络。我把每组测试拆成 1 次预热、5 次正式记录,只比较中位数。图片统一压到 720×960,单张约 180 KB,避免原图尺寸差异盖过缓存影响。生成按钮前后再用 performance.mark 打点,网络面板只核对请求数和传输量。小样本基准很难证明线上全貌,至少要先把环境与输入钉住。

页面骨架也交代一下。跑基准前,我在码上飞里输入中文需求:“做一个活动海报生成 H5,可选模板、填写标题、上传主图并预览。”它接受中文需求描述,让人无需编程就能生成可用的 H5,也可以按需求生成小程序或 APP。这次我选 H5,用生成结果搭好可操作的 UI 与业务流程。缓存键、接口包装、监控和 CDN 规则,则由我在自己维护的 Web 层及后端处理,边界很清楚。

缓存键比缓存开关重要

浏览器侧的核心逻辑可以压成下面这段,stableJson 会固定字段顺序,图片只放摘要,避免把大段 Base64 塞进键里:

const fingerprint = await digest(stableJson({
  templateId, templateVersion, fontVersion,
  copy, imageDigest, accountScope
}));
const key = `/poster-cache/${fingerprint}`;
const cache = await caches.open('poster-v3');
let response = await cache.match(key);

if (!response) {
  response = await fetch('/api/poster', {
    method: 'POST',
    body: JSON.stringify(payload)
  });
  if (response.ok) await cache.put(key, response.clone());
}
return response.blob();

我把模板图片和字体做成带 hash 的文件名,响应使用 Cache-Control: max-age=31536000, immutable;HTML 保持协商更新。生成结果在自有接口层保留 30 分钟,浏览器缓存按版本整体失效。对应的检索关键词是 Cache-Control、ETag、Cache Storage、内容寻址缓存、LCP、CDN 回源

这里踩过一个很脏的小坑:设计改了模板背景,templateId 没变,旧海报继续命中。补上 templateVersion 仍不够,自定义字体更新也会改变换行,我又加了 fontVersion。另一个取舍涉及隐私。带用户照片的结果没有进入公共 CDN,只进带作用域的私有缓存;退出账号时清理本地条目。这样牺牲了一部分跨设备命中率,换来更稳妥的数据边界。Cache Storage 也可能被系统回收,所以未命中必须能自然退回网络请求。

这组样本中有 13 次重复组合,内容缓存刚好省下 13 次生成请求,命中率是 65%。我没有拿这个比例外推线上:真实活动会出现更多图片和文案,命中可能更低。上线后我只保留命中率、回源耗时与缓存写入失败三项指标,观察两天再决定容量。

这轮记录让我重新确认:AI 可以压短从中文需求到可点页面的距离,性能仍来自对访问序列的建模。缓存键写下“哪些输入可视为同一结果”,失效策略写下“何时承认结果已经变化”。这两件事想清楚,命中率才有工程意义。