不能直接对用户上传图用 降级,因为其是运行时动态内容,服务端未生成多格式副本前html已渲染完成,动态插入无效且导致布局抖动。

用户上传的图片不能靠 <picture></picture> 或 srcset 降级,必须由服务端生成多格式 + 多尺寸副本,并在 HTML 中用 <img> 静态写死可用路径;前端 JS 上传后若未完成转码,应 fallback 到原始文件(如 JPEG)并显式控制宽高。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
为什么不能直接对用户上传图用 <picture></picture> 降级
用户上传的图片是运行时动态内容,不是构建时可预知资源。你无法在 HTML 模板里提前写出 <source type="image/webp"></source>,因为:
- 服务端还没来得及生成 WebP/AVIF 副本,HTML 已经渲染完成
- 即使 JS 后续插入 <picture></picture>,浏览器不会重新触发 onload 或 error 事件,旧图已加载完毕
- <picture></picture> 的 <source></source> 必须在 DOM 解析阶段就存在,动态插入不生效(尤其在 Safari 和旧 WebView 中)
- 用户上传的 JPEG 可能缺失 EXIF 宽高,导致后续 WebP 替换时 intrinsic 尺寸不一致,引发 layout shift
服务端必须同步生成 WebP + JPEG 双格式副本
上传成功后,服务端不能只存一份原始图,而要立即生成至少两套输出:
- 主力格式(如 WebP):用于现代浏览器,体积小、质量可控
- 兜底格式(JPEG):必须是标准 image/jpeg MIME 类型,不含查询参数(如 ?x-oss-process=...),且宽高像素与 WebP 完全一致
- 所有副本需写入完整 EXIF ImageWidth/ImageHeight 字段,避免浏览器误判为“无尺寸”
- 不要用 CDN 动态转码路径作为兜底 src,它返回的 HTTP Content-Type 可能不稳定,且不保证元数据完整
前端渲染时用 <img> 直接引用静态路径
服务端返回 JSON 数据中,应包含明确的、已生成的各格式 URL,前端不做条件判断,直接写入 <img>:
- src 必须指向一个真实存在的、可直访的 JPEG 路径(如 /u/abc123.jpg)
- 不要留空、不要写 data-src、不要依赖 JS 补充——断网或 JS 错误时,这张图仍要显示
- 如果业务允许,src 可指向 LQIP(低质量占位图),但必须是完整 JPEG,不能是 base64 或 SVG
- 必须显式设置 width 和 height 属性,或用 CSS aspect-ratio 锁定容器比例,防止布局抖动
上传未完成转码时的临时 fallback 策略
服务端转码可能耗时数秒,前端不能干等。此时应:
- 上传响应中返回原始文件路径(如 original_url: "/u/abc123.png")和状态字段(如 is_transcoded: false)
- 前端优先用该原始路径做 src,并加 loading="eager" 确保立即加载
- 同时轮询转码状态,一旦完成,用 img.src = webp_url 替换(注意:替换后需手动触发 img.onload 逻辑,否则 object-fit 等样式可能不重绘)
- 若轮询超时,保持原始图,不强求切换——用户体验比格式统一更重要
最易被忽略的是:所有用户上传图的宽高元数据必须由服务端强制标准化,前端不能假设“同一张图的不同格式尺寸一致”。哪怕只是少 1 像素,aspect-ratio 也会失效,object-fit: cover 会裁错位置。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










