图片懒加载与压缩:减少请求与传输体积
图片懒加载与压缩
为什么需要优化图片
图片通常是网页中体积最大的资源,占用大量带宽。未优化的图片会直接导致页面加载缓慢、用户体验下降,尤其在移动网络下更为明显。通过懒加载(按需请求)与压缩(减小传输体积),可以显著降低首屏加载时间、节省服务器流量,并提升 Core Web Vitals 等性能指标。
本教程将从零讲解图片懒加载与压缩的核心概念,并提供可直接上手的实现方案,帮助你立即改善网站性能。
图片懒加载
懒加载是什么
懒加载是一种延迟加载策略:只有当图片即将进入浏览器可视区域时,才去加载对应的图片资源。未出现在屏幕范围内的图片不会被请求,从而减少首屏并发请求数和传输体积,加快页面初始渲染。
实现方式一:使用 loading="lazy" 属性
现代浏览器原生支持懒加载,这是最简单的方法。只需在 <img> 标签上添加 loading="lazy" 即可。
<img src="photo.jpg" alt="示例图片" loading="lazy" />
属性值说明
lazy:延迟加载图片,直到图片距离视口一定距离时开始加载。eager(默认):立即加载图片,无论是否在视口内。
注意事项
- 浏览器兼容性:Chrome 77+、Firefox 75+、Edge 79+ 等均支持,Safari 从 15.4 开始支持。对于不支持的浏览器,可配合 JavaScript 方案兜底。
- 不要对首屏关键图片使用
lazy,否则可能延迟首屏展示,影响 LCP 指标。
实现方式二:使用 Intersection Observer(JavaScript)
当需要更精确的控制或兼容旧浏览器时,可以借助 Intersection Observer API 手动实现懒加载。
核心思路
- 将图片的真实地址存储在
data-src属性中,src可设置占位图或留空。 - 创建一个 Observer 实例,监听目标图片是否进入视口。
- 当图片进入视口时,将
data-src的值赋值给src,触发加载。 - 加载完成后取消监听,避免重复操作。
代码示例
<img class="lazy" data-src="photo.jpg" src="placeholder.jpg" alt="懒加载图片" />
const lazyImages = document.querySelectorAll('img.lazy');
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
obs.unobserve(img);
}
});
}, {
rootMargin: '50px 0px', // 提前50px开始加载,提升体验
threshold: 0.01
});
lazyImages.forEach(img => observer.observe(img));
} else {
// 兜底方案:直接加载所有图片或使用旧式滚动监听
lazyImages.forEach(img => {
img.src = img.dataset.src;
});
}
要点解释
rootMargin可以设置触发偏移,让图片在即将进入视口前就开始加载,避免用户滑动时看到空白。threshold表示可见比例达到多少时触发回调,一般设为接近 0 即可。- 对于不支持 Intersection Observer 的浏览器(如 IE),需要提供降级处理,比如直接加载所有图片。
实践建议
- 所有非首屏图片均开启懒加载,包括列表、文章正文配图等。
- 给图片设置明确的宽高属性或使用
aspect-ratio预留空间,防止加载后页面发生布局跳动,改善 CLS(累积布局偏移)。 - 对于背景图片懒加载,可通过 JavaScript 监测元素可见性后动态修改 CSS
background-image。
图片压缩
压缩的核心概念
图片压缩的目的是在可接受的视觉质量下,尽可能减小文件体积。压缩可分为两类:
- 有损压缩:通过丢弃部分视觉信息来大幅减小体积,会不可逆地损失画质。常用于照片、渐变色丰富的场景。
- 无损压缩:仅通过优化编码方式减小体积,完全保留原始画质。适合图标、Logo、简单图形等对清晰度要求极高的场景。
选择正确的图片格式
不同的图片格式具有不同的压缩效率和应用场景,选用正确格式本身就能显著减少体积。
| 格式 | 压缩类型 | 透明度支持 | 典型适用场景 |
|---|---|---|---|
| JPEG | 有损 | 不支持 | 照片、复杂图像、截图 |
| PNG | 无损(也可有损) | 支持 | 图标、透明背景图、界面元素 |
| WebP | 有损/无损/透明 | 支持 | 几乎所有场景,体积比 JPEG/PNG 小 25%~35% |
| AVIF | 有损/无损/透明 | 支持 | 新一代高效格式,体积更小,质量更高 |
| SVG | 矢量(可无损) | 支持 | 图标、插图、可缩放图形 |
格式选择建议
- 优先使用 WebP 作为主力格式,现代浏览器支持率超过 97%。
- 如果需要更优压缩,可考虑 AVIF,但注意 Safari 等兼容性。
- 对于矢量图形,优先使用 SVG,它可缩放且文件极小。
- 在需要透明度且 WebP 不可用时,使用 PNG。
- JPEG 仍可作为照片的兜底格式。
压缩工具与方法
手动压缩(开发阶段使用)
- 在线工具:Squoosh、TinyPNG、JPEGmini。Squoosh 支持 WebP、AVIF 导出,可实时预览质量。
- 命令行工具:
imagemagick:convert input.jpg -quality 80 output.jpgcwebp(WebP 官方工具):cwebp -q 80 input.png -o output.webp
- 图像处理软件:Photoshop(存储为 Web 所用格式)、GIMP 等导出时调节质量参数。
自动化压缩(构建流程集成)
推荐将图片压缩集成到项目构建流程中,避免手动操作。
使用 Webpack 的 image-webpack-loader
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'file-loader',
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: { progressive: true, quality: 75 },
optipng: { enabled: true },
pngquant: { quality: [0.65, 0.8], speed: 4 },
webp: { quality: 75 }
}
}
]
}
]
}
}
使用 Gulp + 插件 或 imagemin 命令行工具也能实现类似效果。
服务端动态压缩
如果用户上传图片,可以在服务器端自动生成压缩版本或多尺寸响应式图片。例如使用 Node.js 的 sharp 库:
const sharp = require('sharp');
sharp('input.jpg')
.resize(800)
.webp({ quality: 80 })
.toFile('output.webp');
可以结合 CDN 服务(如 Cloudinary、Imgix)动态转换图片格式与尺寸,无需自行处理。
响应式图片与压缩结合
利用 <picture> 和 srcset 属性,根据屏幕宽度和像素密度加载不同尺寸的图片,避免在小屏幕上加载大尺寸原图。
<picture>
<source srcset="photo-large.avif" type="image/avif" media="(min-width: 800px)" />
<source srcset="photo-medium.avif" type="image/avif" media="(min-width: 400px)" />
<source srcset="photo-large.webp" type="image/webp" media="(min-width: 800px)" />
<source srcset="photo-medium.webp" type="image/webp" media="(min-width: 400px)" />
<img src="photo-small.jpg" alt="响应式图片" loading="lazy" />
</picture>
这样浏览器会按优先级选择支持的格式和合适的尺寸,既压缩了体积,又兼顾了清晰度。
懒加载与压缩的组合策略
前端整体加载流程
- HTML 中使用
loading="lazy"或 data-src 占位,并预设尺寸占位元素。 - 构建时压缩所有图片,生成多种格式(JPEG/WebP/AVIF)和多种尺寸。
- 通过
<picture>+srcset提供响应式资源。 - 浏览器仅加载进入视口的图片,并自动拣选最优格式。
- 首屏关键图片(如Hero Banner)使用
eager加载,避免延迟。
性能收益评估
- 请求数量:懒加载可减少 50~70% 的首屏图片请求,尤其适合长页面。
- 传输体积:WebP/AVIF 相比 JPEG 可节省 30~50%,加上多尺寸响应式可再减半。
- 指标提升:LCP 优化,CLS 降低,首屏载入时间明显缩短。
注意事项
- 不要过度压缩导致图片失真,建议采用 75~85% 的质量系数,并使用实际人眼评估。
- 为每个
img标签定义width和height属性,或使用 CSSaspect-ratio,是防止布局偏移的关键。 - 对于首屏大图,可考虑使用渐进式 JPEG 或先显示低质量模糊预览(LQIP),提升感知速度。
通过懒加载与压缩的组合应用,你可以用最简单的手段获得巨大的性能回报。推荐从当前项目入手,先启用原生懒加载,再逐步引入自动化压缩和现代格式,让网页图片既轻又快。