1. 课程导入

大家好,我是这次课程的主讲。做了这么多年前端,我越来越觉得图片管理这事儿,看着简单,实则是个深坑。你想想看,一个页面里动辄几十张图,加载慢、内存爆、切换卡顿,十有八九都是图片没管好。

今天咱们就来聊聊,为什么非得把图片资源当回事儿。

一、为什么需要管理图片资源

说白了,图片是页面里最重的资源。一个中等规模的电商页面,图片体积能占到总资源量的 60% 以上。我见过一个项目,首页首屏加载了 3MB 的图片,用户等得直骂娘。

管理图片资源,核心原因就三个:

  • 用户体验:图片加载慢,用户扭头就走。数据表明,页面加载延迟 1 秒,转化率下降 7%。
  • 带宽成本:图片体积大,CDN 流量蹭蹭往上涨。公司每个月多花几万块,老板肯定找你谈话。
  • 内存占用:移动端内存本来就紧张,一张 4000x3000 的图解码后能占 48MB。页面切来切去,内存泄漏了都不知道。

核心观点:图片管理不是「要不要做」的问题,而是「怎么做才能少踩坑」的问题。

二、图片加载对页面性能的影响

我习惯把图片加载对性能的影响分成三个阶段来看。每个阶段都有它的瓶颈。

阶段 影响指标 典型问题
网络传输 LCP、FCP、TTFB 图片体积大、并发请求多、弱网环境超时
解码渲染 FPS、帧率抖动 大图解码耗时、GPU 内存溢出、Canvas 重绘
内存占用 页面崩溃、卡顿 未释放的 Image 对象、离屏 Canvas 残留

举个例子。我之前做过一个图片社交 App,用户刷瀑布流时,图片一张接一张加载。刚开始没做管理,结果 iPhone 6s 上直接闪退。查了半天,发现是图片解码后占用了 200MB 内存,系统直接杀了进程。

为什么会这样?因为浏览器加载图片时,会先下载原始文件,然后解码成位图,最后才渲染到屏幕上。每一步都有代价。

避坑提醒:我曾经以为只要压缩图片就万事大吉,结果发现解码和内存才是移动端的真正杀手。压缩只能解决网络传输的问题,内存管理得单独处理。

三、图片管理的基本原则

做了这么多年,我总结出四条基本原则。你照着做,至少能避开 80% 的坑。

1. 按需加载,不提前加载

用户没看到的图片,就别急着加载。尤其是页面切换场景,当前页面还没看完,下一屏的图就已经开始下载了,白白浪费带宽。

  • 使用 IntersectionObserver 实现懒加载
  • 预加载只用于「用户即将看到」的图片
  • 离开页面时取消未完成的请求

2. 尺寸匹配,不放大不缩小

我见过太多人把 2000px 宽的图直接塞进 300px 的容器里。浏览器虽然能缩放,但解码成本一点没少。

  • 根据容器尺寸生成对应分辨率的图片
  • 使用 srcset 和 sizes 属性适配不同屏幕
  • 移动端优先使用 2x 图,但不要超过实际需要

3. 格式选对,事半功倍

不同图片格式有各自的适用场景。选错了,体积翻倍不说,兼容性也出问题。

格式 适用场景 注意事项
WebP 照片、复杂渐变图 iOS Safari 14+ 才支持,需要 fallback
AVIF 高压缩比需求 解码较慢,适合大图但不宜过多
JPEG/PNG 兼容性兜底 体积大,尽量少用
SVG 图标、插画、简单图形 复杂路径反而比 PNG 大

4. 及时释放,不留隐患

页面切换时,旧页面的图片资源必须清理干净。否则内存只增不减,用户多切几次页面就卡死了。

  • 组件销毁时取消图片请求
  • 手动将 Image 对象的 src 置空
  • 使用 WeakMap 管理图片引用,避免内存泄漏

我的习惯:每次写图片组件,我都会在 unmount 钩子里加一段清理逻辑。别嫌麻烦,这能救你于水火之中。

四、图片资源管理的知识体系

下面这张图是我自己梳理的,把图片管理的核心脉络画出来了。你一看就明白。

图片资源管理知识体系 图片资源管理 按需加载 尺寸匹配 格式选对 及时释放 IntersectionObserver 预加载策略 请求取消 srcset / sizes 响应式图片 容器适配 WebP / AVIF JPEG / PNG 兜底 SVG 图标 组件销毁清理 src 置空 WeakMap 引用 四条原则相互配合,缺一不可 按需加载 + 尺寸匹配 + 格式选对 + 及时释放 = 高效管理

嗯,这张图基本把本章的核心内容串起来了。后面的课程,我们会逐一深入每个分支,讲具体怎么落地。

五、小结

这一章我们聊了图片资源管理为什么重要,它对性能的影响有多大,以及四条基本原则。说白了,图片管理不是锦上添花,而是基本功。你想想看,一个页面切换流畅、内存稳定、加载飞快的应用,背后一定有一套扎实的图片管理方案。

我个人建议,从现在开始,每张图都问自己三个问题:这张图用户现在需要看吗?尺寸合适吗?格式对吗?养成习惯,后面会省很多事。