跳到主要内容

图片优化与自适应策略

1. 格式选择​

格式压缩透明动画浏览器支持适合
AVIF最优(比 WebP 小 20-30%)✓✓Chrome 85+, Firefox 93+首选
WebP优(比 JPEG 小 25-35%)✓✓全主流通用
JPEG中✗✗全部fallback
PNG无损✓✗全部图标/截图
SVG矢量✓✓全部图标/logo

决策:AVIF > WebP > JPEG。用 <picture> 渐进增强。

2. <picture> 渐进增强​

<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" decoding="async">
</picture>

浏览器按顺序选第一个支持的格式。

3. 响应式图片(srcset + sizes)​

<img
srcset="
hero-400.webp 400w,
hero-800.webp 800w,
hero-1200.webp 1200w,
hero-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
src="hero-800.webp"
alt="Hero"
width="1200"
height="600"
loading="lazy"
decoding="async"
/>

浏览器根据 viewport + 设备像素比选合适尺寸。

sizes 含义:

  • 视口 ≤ 600px → 图片占满宽度(100vw)
  • 视口 ≤ 1200px → 图片占一半(50vw)
  • 更大 → 固定 800px

4. 懒加载​

<!-- 首屏图不要 lazy(影响 LCP) -->
<img src="hero.webp" fetchpriority="high" alt="Hero">

<!-- 非首屏图 -->
<img src="thumb.webp" loading="lazy" decoding="async" alt="...">

loading="lazy" 原生支持。交叉观察器(IntersectionObserver)更灵活但一般不需要。

4.1 首屏 LCP 图片优化​

<!-- preload + fetchpriority -->
<link rel="preload" as="image" href="hero.avif" type="image/avif"
imagesrcset="hero-400.avif 400w, hero-800.avif 800w"
imagesizes="100vw">

<img src="hero.avif" fetchpriority="high" alt="Hero"
width="1200" height="600">

LCP 图片不要懒加载 + 要 preload + 要 fetchpriority="high"。

5. CDN 图片处理​

各 CDN 支持 URL 参数实时处理:

5.1 阿里云 OSS​

https://bucket.oss-cn-hangzhou.aliyuncs.com/photo.jpg?x-oss-process=image/resize,w_800/format,webp/quality,Q_80

5.2 Cloudflare Images​

https://example.com/cdn-cgi/image/width=800,format=auto,quality=80/photo.jpg

format=auto 根据 Accept 头自动选 AVIF / WebP / JPEG。

5.3 Imgix / Cloudinary​

https://myapp.imgix.net/photo.jpg?w=800&auto=format&q=80

6. 构建时优化​

6.1 sharp(Node)​

npm i sharp
const sharp = require('sharp')

// 批量转 WebP + AVIF
await sharp('input.jpg')
.resize(800)
.webp({ quality: 80 })
.toFile('output.webp')

await sharp('input.jpg')
.resize(800)
.avif({ quality: 60 })
.toFile('output.avif')

6.2 Vite 插件​

// vite.config.ts
import { viteImagemin } from 'vite-plugin-imagemin'

export default {
plugins: [
viteImagemin({
gifsicle: { optimizationLevel: 3 },
mozjpeg: { quality: 80 },
pngquant: { quality: [0.7, 0.9] },
webp: { quality: 80 },
avif: { quality: 60 },
})
]
}

6.3 Next.js Image​

import Image from 'next/image'

<Image
src="/hero.jpg"
width={1200}
height={600}
alt="Hero"
priority // 首屏
placeholder="blur" // 模糊占位
blurDataURL="data:image/..."
/>

Next.js Image 自动:

  • 按设备 srcset
  • WebP / AVIF 自动协商
  • 懒加载(非 priority)
  • 防 CLS(必填 width/height)

7. 占位策略​

防 CLS + 提升感知速度:

7.1 固定宽高​

<img width="800" height="600" src="..." alt="...">

CSS aspect-ratio 等效:

img { aspect-ratio: 4/3; width: 100%; height: auto; }

7.2 LQIP(低质量占位)​

构建时生成 10px 缩略图 base64:

<img src="full.webp" style="background: url(data:image/jpeg;base64,...) no-repeat center/cover">

7.3 BlurHash​

import { encode } from 'blurhash'
// 编码为 4x3 的 hash 字符串
const hash = encode(imageData, 4, 3)
// 前端 decode 渲染 canvas

更小的占位表示。

7.4 CSS dominant color​

<div style="background-color: #3a7bd5; aspect-ratio: 16/9;">
<img loading="lazy" src="..." alt="...">
</div>

8. SVG 优化​

# SVGO 压缩
npx svgo input.svg -o output.svg

# 批量
npx svgo -f ./src/icons/ -o ./dist/icons/
// svgo.config.js
module.exports = {
plugins: [
'preset-default',
{ name: 'removeViewBox', active: false },
'removeDimensions',
]
}

9. 视频替代 GIF​

GIF 体积巨大。用 &lt;video> 替代:

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

WebM 通常比等效 GIF 小 80%+。

10. 性能预算​

{
"size-limit": [
{ "path": "dist/images/**/*.{jpg,png,webp}", "limit": "500 KB" }
]
}

单页总图片传输 < 1MB(移动端)。

11. 监控​

// 慢图片上报
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.initiatorType === 'img' && entry.duration > 2000) {
reportSlowImage({
url: entry.name,
size: entry.transferSize,
duration: entry.duration,
})
}
}
}).observe({ type: 'resource', buffered: true })

12. 常见反模式​

  • 首屏 LCP 图 lazy load:LCP 变慢
  • 不设 width/height:CLS
  • 2000px 图给 400px 容器:浪费带宽
  • 不用 WebP / AVIF:多 30-50% 体积
  • PNG 存照片:应该 JPEG/WebP
  • GIF 动图:用 video 代替
  • 图片不走 CDN:回源慢
  • 不限最大尺寸:用户上传 10MB 原图
  • 所有图 fetchpriority="high":等于没标
  • SVG 不压缩:可能含几十 KB 无用 metadata

13. 延伸阅读​