前言
本文总结 web 性能优化中图片优化的相关知识点。
一些背景知识
有损压缩(Lossy Compression)
有损压缩是一种图像压缩方法,通过牺牲一些图像细节以减小文件大小。JPEG 是一种常见的有损压缩图像格式。在压缩过程中,一些数据被永久性地丢失,因此每次重新保存图像时都会损失一些质量。
无损压缩(Lossless Compression)
无损压缩是一种图像压缩方法,可以减小文件大小但不会导致任何图像细节的永久性丢失。PNG 和 GIF 是常见的无损压缩图像格式。无损压缩对于需要保留原始图像质量的情况非常重要。
通道(Channel)
图像通道是指图像中的颜色信息分离成的不同部分。对于 RGB 图像,有三个通道,分别对应红色、绿色和蓝色。每个通道都包含图像中相应颜色的亮度信息。
Alpha 通道是图像中的额外通道,用于表示每个像素的透明度。RGBA 图像中的 A 表示 Alpha 通道,它控制像素的不透明度。
位图(Bitmap)
位图是由像素组成的图像,每个像素都有特定的颜色信息。JPEG、PNG 和 GIF 都是位图格式。缩放位图可能导致图像失真,特别是当放大图像时。
矢量图(Vector Graphic)
矢量图使用数学公式表示图像,而不是像素。它们可以无限缩放而不失真,因此适用于图标、标志等需要在不同尺寸下保持清晰度的图像。SVG(可缩放矢量图形)是一种常见的矢量图格式。
索引色(Indexed Color)
索引色是一种图像色彩模式,其中颜色信息存储在一个颜色索引表中。每个像素的颜色通过索引而不是直接的 RGB 值来表示。GIF 图像通常使用索引色。
直接色(Direct Color)
直接色是一种图像色彩模式,其中每个像素的颜色直接由 RGB 值表示,而不是通过索引。JPEG 和 PNG 图像通常使用直接色。
几种常见的图片格式
当选择图片格式时,需要考虑文件大小、图像质量、透明度和动画等因素。
JPEG
JPEG(JPG)是一种有损压缩的图像格式,主要适用于照片和真实场景图像。它的优点在于相对较小的文件大小和在高压缩比下保持较好的图像质量,但缺点是有损压缩可能导致图像细节的损失,而且不支持透明度。因此,JPEG 通常用于对图像质量要求较低,但需要高效传输的情况。
适用场景举例:
- 照片展示:适用于网站上的照片展示、摄影作品等。
- Banner 图:用于网站首页的大型横幅图片。
- 图片背景:适合作为页面或元素的背景图。
PNG
PNG 是一种无损压缩的图像格式,特别适用于图形、图标和需要透明度的图像。它的优点在于支持透明度、无损压缩以及保持图像质量,但缺点是文件大小通常较大,不如 JPEG 适合压缩照片。PNG 常被选择用于需要保留细节并且支持透明背景的图像,如图标和图形。
适用场景举例:
- 图标和图形:适用于包含透明度要求的图标和图形。
- 网站 Logo:常用于需要带有透明背景的网站 Logo。
- 屏幕截图:适合捕捉屏幕截图,并保留细节和透明背景。
GIF
GIF 是一种支持动画的图像格式,适用于简单动画和图形。它的优点包括支持透明度和动画,文件大小相对较小。然而,由于其色彩深度较低,不适用于照片等复杂图像。因此,GIF 通常被用于制作简单图形、图标以及需要动画效果的场景。
适用场景举例:
- 简单动画:适用于制作简单的循环动画,如 loading 图标。
- 表情动图:适合在聊天应用或社交媒体上使用的表情动图。
SVG
SVG(可缩放矢量图形)是一种基于 XML 的矢量图像格式,可无损缩放而不失真。它适用于图标和图形,可以通过文本编辑器进行编辑。SVG 的优点包括适用于响应式设计,可缩放且不失真,可以通过 CSS 和 JavaScript 进行交互。然而,SVG 不适用于包含复杂图像细节的照片,因为它是矢量图形格式。SVG 通常用于制作图标和简单图形,以及需要响应式设计的情况。
适用场景举例:
- 响应式设计:适用于需要适应不同屏幕尺寸的图形,如网站图标。
- 图标集:用于创建可缩放的图标集,以便在不同大小的容器中使用。
- 数据可视化:适合在数据可视化方面使用,如图表和地图。
WebP
WebP 是由 Google 开发的图像格式,支持有损和无损压缩,通常具有更好的压缩效果。它的优点包括较小的文件大小、支持透明度和动画。然而,由于兼容性问题,某些旧版本浏览器可能不支持 WebP 格式,这是一个需要考虑的缺点。WebP 适用于需要更好压缩效果和支持透明度、动画的场景。
适用场景举例:
- 网站图像压缩:适用于需要更小文件大小的网站图像。
- 高质量图形:用于需要保持高质量的图形,同时获得更好的压缩效果。
- 动画广告:适合创建轻量级的动画广告。
web 性能优化中的图片优化
选择合适的图片格式
根据图像内容选择最适合的图片格式,JPEG、PNG、WebP、SVG 各有优势。
图片压缩
使用工具(ImageOptim、TinyPNG、JPEGoptim)对图片进行压缩,减小文件大小,提高页面加载速度。
webpack 中可以使用 image-webpack-loader 对图片进行压缩。
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 80,
},
},
},
],
},
],
},
懒加载
图片懒加载是一种优化网页性能的技术,它通过延迟加载页面上的图片,直到图片进入用户视野(可见区域)时才进行加载。这有助于减少页面加载时间,特别是在包含大量图片的长页面上。
基本原理如下:
-
页面初次加载时,只加载可见区域内的图片,而对于在用户当前视野之外的图片,不提前加载。
-
当用户滚动页面,当图片进入可见区域时,通过 JavaScript 触发图片的加载,从而实现逐步加载。
在这个示例中,使用 data-src 属性保存图片的真实 URL,而 src 属性则设置一个占位图像或加载中的图像。使用 JavaScript 检测滚动事件,当图片进入可见区域时,将 data-src 的值赋给 src,触发实际的图片加载。
完整的 demo 请看 👉 在线效果预览, 查看示例代码请点击此处
实现响应式图片
根据用户设备的屏幕尺寸和分辨率动态加载适当尺寸的图片,以提高网页性能。常见的方法有以下几种:
使用元素
元素允许在不同的屏幕尺寸或分辨率下为用户提供不同的图片源。
<picture>
<source media="(max-width: 600px)" srcset="small.jpg" />
<source media="(max-width: 1200px)" srcset="medium.jpg" />
<img src="large.jpg" alt="Description" />
</picture>
使用 srcset 属性
srcset 属性允许指定一组适用于不同设备和分辨率的图片。浏览器会根据用户设备的特性自动选择合适的图片。
<img
srcset="small.jpg 600w, medium.jpg 1200w, large.jpg 1800w"
sizes="(max-width: 600px) 90vw,
(max-width: 1200px) 60vw,
100vw"
src="large.jpg"
alt="Description"
/>
使用 CSS 媒体查询
使用 CSS 媒体查询,根据不同的屏幕尺寸和分辨率应用不同的样式,包括不同尺寸的图片。
@media (max-width: 600px) {
.responsive-image {
background-image: url("small.jpg");
}
}
@media (max-width: 1200px) {
.responsive-image {
background-image: url("medium.jpg");
}
}
@media (min-width: 1201px) {
.responsive-image {
background-image: url("large.jpg");
}
}
使用 JavaScript
使用 JavaScript 检测屏幕尺寸和分辨率,动态加载适当尺寸的图片。
<script>
if (window.matchMedia("(max-width: 600px)").matches) {
document.getElementById("responsiveImage").src = "small.jpg";
} else if (window.matchMedia("(max-width: 1200px)").matches) {
document.getElementById("responsiveImage").src = "medium.jpg";
} else {
document.getElementById("responsiveImage").src = "large.jpg";
}
</script>
通常,结合使用元素和 srcset 属性是一种简便而灵活的方法,而 CSS 媒体查询和 JavaScript 适用于更复杂的情况。
图片预加载和预渲染
图片预加载
在页面加载之前提前加载一些图片,使它们在需要显示时能够迅速加载,而不用等到用户请求加载时再加载。
实现方式:
- 使用
<link>
标签的 rel 属性进行预加载:
<link rel="preload" href="image.jpg" as="image" />
图片预渲染
雪碧图(不推荐使用)
虽然雪碧图技术在过去被广泛用于合并多个小图标以减少 HTTP 请求次数,但随着前端技术的发展,它已经逐渐显得有些过时, 主要原因如下
-
HTTP/2 支持多路复用,允许在同一连接上同时发送多个请求。在 HTTP/2 中,同时请求多个小文件与请求一个大文件的性能差异不大。因此,减少 HTTP 请求的优势在 HTTP/2 环境下减弱。
-
HTTP 请求的并行处理:现代浏览器能够更有效地处理并行下载多个小文件。浏览器在加载资源时,会在并行下载多个文件,因此小图标的多次请求不再像过去那样显著影响性能。
-
矢量图标的兴起:随着 SVG 格式的广泛应用,矢量图标成为一种更现代、灵活且可缩放的替代方案。矢量图标不需要合并成雪碧图,而是以独立的文件形式存在,更容易维护和更新。
本文首发于个人博客前端开发笔记,由于笔者能力有限,文章难免有疏漏之处,欢迎指正