Web 图像优化清单:格式 / 尺寸 / 懒加载 / responsive

图像是网页最大的字节来源。下面是一份能让 Lighthouse 分数从 60 涨到 95
的实战清单。

1. 用对格式

  • AVIF:2024 主流浏览器都支持,文件最小,复杂图比 WebP 还小 20-30%
  • WebP:兼容性更广(IE11 之外都行),编码快
  • JPEG:照片,进度加载支持好
  • PNG:透明背景、像素图 / icon
  • SVG:矢量图(logo、icon)

服务端按 Accept 头返回最佳格式:

<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="Hero" width="1200" height="600" loading="lazy">
</picture>

浏览器从上到下选第一个支持的。<img> 是兜底。

2. 永远写 width / height

<img src="thumb.jpg" alt="" width="320" height="180">

让浏览器在加载图片前知道占位空间,避免 CLS(Cumulative Layout Shift)。
没写的图片加载完会"撑开"页面跳动。

CSS 控制实际尺寸:

img { max-width: 100%; height: auto; }

但 HTML 的 width/height 用来告诉浏览器宽高比(aspect ratio),必加。

3. responsive:不同视口不同尺寸

<img
  src="hero-800.jpg"
  srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
  alt="Hero"
  width="1600" height="800"
>

srcset 提供多分辨率,sizes 告诉浏览器图片实际显示大小,
浏览器结合 device pixel ratio 选最优 src。

4. lazy loading(原生属性)

<img src="below-fold.jpg" loading="lazy" alt="" width="..." height="...">
<iframe src="..." loading="lazy"></iframe>

loading="lazy" 让浏览器在元素进入视口前不加载。
首屏 / above-the-fold 的图片不要加(用 loading="eager" 默认)。

5. decoding="async"

<img src="x.jpg" loading="lazy" decoding="async">

让浏览器异步解码图片,不阻塞主线程。

6. priority hints

首屏关键图加 fetchpriority="high"

<img src="hero.jpg" fetchpriority="high" loading="eager">

预加载 + 高优先级,关键内容更快出现。LCP(Largest Contentful Paint)
指标提升明显。

7. preload 关键资源

<link rel="preload" as="image"
      href="hero.jpg"
      imagesrcset="hero-800.jpg 800w, hero-1600.jpg 1600w"
      imagesizes="100vw">

页面 head 里 preload 首屏大图,浏览器立刻并行下载。

8. CDN 上做实时转换

https://your-cdn.example.com/image?src=foo.jpg&w=800&fmt=avif

CDN 收到请求后按参数生成对应格式 / 尺寸,缓存返回。

服务:Cloudinary、imgix、Cloudflare Images、Bunny.net、自己用 imgproxy
搭建。

9. 工具:批量优化

# AVIF
npm install -g sharp-cli
sharp -i 'images/*.jpg' -o 'dist/' avif --quality 60

# WebP
cwebp -q 80 input.png -o output.webp

# JPEG 进度 + mozjpeg 优化
mozjpeg -quality 80 -progressive -outfile out.jpg in.jpg

# PNG 优化
pngquant --quality=70-90 in.png   # 有损但视觉无差
oxipng --opt 4 in.png             # 无损

# SVG
svgo -i in.svg -o out.svg

CI 阶段把 source 全转一遍。

10. Next / Vite 框架内置

Next.js

import Image from 'next/image'

<Image
  src="/hero.jpg"
  width={1200} height={600}
  alt="Hero"
  priority   // 首屏 LCP
  placeholder="blur"
/>

next/image 自动生成多分辨率 + AVIF / WebP + 懒加载。

Vite

vite-imagetools plugin:

import hero from './hero.jpg?w=400;800;1600&format=avif;webp;jpg&as=picture'
<img {...hero} loading="lazy" />

Build 时自动生成所有尺寸 / 格式 + 注入 srcset。

11. 模糊占位符(LQIP)

预生成 base64 编码的极小图当占位:

<img src="data:image/jpeg;base64,/9j/..." />
<!-- 同时异步加载真图,加载完替换 -->

或者用 BlurHash 算法(更紧凑,几十字节)。Next.js placeholder="blur"
自动做这个。

12. SVG sprite(多个 icon)

<svg style="display:none">
  <symbol id="icon-cart" viewBox="0 0 24 24">
    <path d="..." />
  </symbol>
</svg>

<!-- 使用 -->
<svg><use href="#icon-cart" /></svg>

一次下载所有 icon,按需引用,比 icon font 性能 / 灵活性都好。

13. 验证

Lighthouse / WebPageTest 跑一遍:

  • LCP < 2.5s ✅
  • CLS < 0.1 ✅
  • 没有 "Properly size images" 警告
  • 没有 "Serve images in next-gen formats" 警告

14. 视频替代 GIF

GIF 巨大 + 不可压缩。替代:

<video autoplay loop muted playsinline>
  <source src="anim.webm" type="video/webm">
  <source src="anim.mp4" type="video/mp4">
</video>

同一段动画 WebM 通常比 GIF 小 80-90%。

踩过的坑

  • <img src= 但没写 width/height → CLS 0.3+ 直接红色。
  • AVIF 编码慢(CPU 几秒一张):build 时缓存输出,不要每次重编码。
  • responsive srcset 算错 sizes → 浏览器选了过大或过小的图。
    开 DevTools 看 Network 实际请求的 URL 校验。
  • "压缩太狠" → JPEG quality 60 以下肉眼可见 artifact。建议 70-85
    甜点。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。