网页图片优化——深入指南
目录
未优化(未压缩)的图片是导致网站性能不佳的主要原因之一,尤其是在初始加载时。根据分辨率和图片质量,图片最终可能会占据网站总大小的 70% 以上。
未经优化的图片很容易出现在生产网站上,并显著降低其初始加载速度。缺乏经验的开发人员通常意识不到这个潜在的问题。他们也不了解各种用于优化图片的工具和方法。
本文旨在介绍用于优化网络图像的大多数工具和方法。
计算 JPG 图像文件大小
未压缩图像的大小可以轻松计算出来,只需将图像宽度px
值乘以图像高度px
值,然后将结果乘以3 个字节(相当于 24 位,RGB 颜色系统)。我们将结果除以 ,1,048,576 (1024 \* 1024)
即可将值从字节转换为兆字节。
image_size = (image_width * image_height * 3) / 1048576
例如,让我们计算具有尺寸的未压缩图像的文件大小1366px x 768px
。
1366 * 768 * 3 / 1048576 = 3Mb
考虑到如今网站的平均大小在 2Mb 到 3Mb 之间,想象一下,如果你的网站上有一张图片,其大小超过了网站大小的 80%。在速度较慢的移动网络上,3Mb 的图片加载需要很长时间,因此,如果用户在等待网站加载时,大部分时间都花在加载一张图片上,你可能会损失一些网站流量。想想就觉得可怕,不是吗?
那么我们可以做些什么来避免在网络上优化图像但保持可接受的质量和分辨率呢?
在线图像优化
如果您正在开发一个简单的静态网站,其中只有少量不经常更改或根本不会更改的图片,那么您可以将图片拖放到众多在线工具中。这些工具能够使用各种算法对图片进行出色的压缩,对于简单的项目来说已经足够了。
我认为最值得注意的网站是:
- Compressor.io - JPG、PNG、SVG、GIF - 当时 1 个文件
- Squoosh - JPG、PNG、SVG、GIF - 当时有 1 个文件
- Optimizilla - JPG 和 PNG - 最多可同时处理 20 张图片
- TinyPNG - JPG 和 PNG - 一次最多 20 张图片
- SVGMinify - SVG - 当时 1 个文件
- svgomg - SVG - 当时 1 个文件
自动化解决方案
然而,如果您与多人合作开展更复杂的项目,并使用大量图像,那么在将每张图片添加到项目中时进行优化可能会变得非常繁琐。此外,由于人为错误或其他因素,某些图像最终可能无法优化。
在复杂的项目中,通常使用同样复杂的构建系统,例如Gulp、Webpack、Parcel等。图像优化插件可以轻松添加到这些构建配置中,并完全自动化图像优化过程。图像添加到项目后即可立即进行优化。
在我看来,最值得注意的插件是imagemin,它可以轻松地与任何 CLI 或构建工具集成:
图片加载优化
我们研究了图像优化策略,这些策略通过压缩图像来减小文件大小,而不会改变图像分辨率并过度影响图像质量。虽然优化图像文件可以显著减小文件大小,但同时加载多张优化后的图像(例如,在网店目录页面上)可能会对性能产生不利影响。
延迟加载
延迟加载是指仅加载所需的资源。在我们的例子中,仅加载当前位于用户视口(屏幕)内的图片。其他图片只有在出现在用户视口内时才会加载。
尽管原生的延迟加载刚刚被引入浏览器,但已经有许多基于 JavaScript 的解决方案可用。
原生延迟加载
<img src="image.jpg" loading="lazy" alt="Sample image" />
基于 JavaScript 的解决方案
在我看来,最值得注意的基于 JavaScript 的解决方案是:
渐进式图像
虽然延迟加载在性能方面表现优异,但从用户体验的角度来看,我们可以看到用户在等待图片加载时,会盯着空白处。在网速较慢的情况下,下载图片可能会耗费很长时间。这时,渐进式图片就派上用场了。
简单来说,渐进式图像意味着用户会一直看到一张低质量的图像,直到一张高质量图像加载完毕。由于低质量图像质量低且压缩率高,其文件大小会小得多,因此加载速度会非常快。在低质量和高质量图像之间,我们可以根据需要设置任意数量的不同质量的图像,并在每次下载时加载更高质量的图像。
与我之前写的关于骨架加载的文章类似,这种技术给用户一种速度感。用户看到的是一张正在加载的图像,随着图像质量的提高,图像变得越来越清晰,而不是盯着空白处等待加载。
这是渐进式图像的 JavaScript 实现:progressive-image
响应式图像
我们还需要注意使用适当大小的图像。
例如,假设我们有一张图片,它1920px
在桌面设备上、1024px
平板设备上和568px
移动设备上都达到了最大宽度。最简单的解决方案就是直接用这张1920px
图片覆盖所有情况,对吧?这样一来,如果智能手机用户的网络速度慢且不稳定,就不得不等待很长时间才能下载完这幅巨大的图片,我们又回到了问题的原点。
幸运的是,我们可以使用 picture 元素来告诉浏览器根据媒体查询下载哪张图片。虽然全球超过 93% 的浏览器都支持这个元素,但它有一个非常简单的回退方案,img
即使用元素本身。
<picture>
<source media="(min-width: 1025px)" srcset="image_desktop.jpg">
<source media="(min-width: 769px)" srcset="image_tablet.jpg">
<img src="image_mobile.jpg" alt="Sample image">
</picture>
使用 CDN
Cloudinary 和 Cloudflare 等 CDN 服务可以在服务器上执行图片优化,并将优化后的图片提供给用户。如果您的网站使用 CDN,则值得研究一下资源优化选项。这样,我们完全不用担心图片质量优化,所有优化都在服务器端完成。我们只需要研究如何使用延迟加载或渐进式加载来优化图片加载。
WebP 图像格式
WebP 图片格式由 Google 开发,是一种专门针对 Web 进行优化的图片格式。根据 canIUse 的数据,目前浏览器对 WebP 图片格式的支持率约为 80%,这相当不错。幸运的是,使用元素img
嵌套picture
元素的方式,可以轻松实现回退到标准 jpg 图片。
<picture>
<source type="image/webp" srcset="image.webp" />
<source srcset="image.jpg" />
<img src="image.jpg" alt="Sample image" />
</picture>
虽然有许多在线文件格式转换器可以将图像转换为 WebP 格式,但 CDN 服务可以轻松地在服务器端执行格式转换。
针对高像素密度屏幕进行优化
这更多的是用户体验的改进而不是性能的改进,但考虑具有更高像素密度的设备也很重要。
例如,假设我们在 768px 的屏幕上显示一个 768px x 320px 的横幅图片。但屏幕密度是 2 倍,像素宽度实际上为:2 x 768 = 1536px
。实际上,我们将 768px 拉伸到 1536px 以上,这会导致高像素密度设备上的图像模糊。
为了解决这个问题,我们需要提供针对高像素密度屏幕优化的图像。我们需要创建分辨率为普通屏幕 2 倍或 3 倍的单独图像,并使用srcset
带有2x
标签标记的属性来获取更高分辨率的图像。
<img src="image-1x.jpg" srcset="image-2x.jpg 2x" alt="Sample image" />
示例 - 支持高密度屏幕的响应式 WebP/PNG 图像
<picture>
<source srcset="./images/webp/hero-image-420-min.webp 1x, ./images/webp/hero-image-760-min.webp 2x" type="image/webp" media="(max-width: 440px)">
<source srcset="./images/minified/hero-image-420-min.png 1x, ./images/minified/hero-image-760-min.png 2x" media="(max-width: 440px)">
<source srcset="./images/webp/hero-image-550-min.webp 1x, ./images/webp/hero-image-960-min.webp 2x" type="image/webp" media="(max-width: 767px)">
<source srcset="./images/minified/hero-image-550-min.png 1x, ./images/minified/hero-image-960-min.png 2x" media="(max-width: 767px)">
<source srcset="./images/webp/hero-image-420-min.webp 1x, ./images/webp/hero-image-760-min.webp 2x" type="image/webp" media="(max-width: 1023px)">
<source srcset="./images/minified/hero-image-420-min.png 1x, ./images/minified/hero-image-760-min.png 2x" media="(max-width: 1023px)">
<source srcset="./images/webp/hero-image-760-min.webp 1x, ./images/webp/hero-image-960-min.webp 2x" type="image/webp" media="(max-width: 1919px)">
<source srcset="./images/minified/hero-image-760-min.png 1x, ./images/minified/hero-image-960-min.png 2x" media="(max-width: 1919px)">
<source srcset="./images/webp/hero-image-960-min.webp" type="image/webp">
<source srcset="./images/minified/hero-image-960-min.png">
<img src="./images/minified/hero-image-960-min.png" alt="Example">
</picture>
结论 - 优化优先级
- 使用优化的图像(通过自动构建工具、在线服务或 CDN 进行优化)
- 使用延迟加载(JS 解决方案,直到原生支持更多)
- 针对高像素密度屏幕优化图像
- 使用 WebP 图像格式
- 使用渐进式图像
可选:如果可以的话,请记住通过 CDN 提供图像(和其他静态资产)。
这些文章都是咖啡带来的灵感。所以,如果你喜欢我的文章,觉得它有用,不妨请我喝杯咖啡!我会非常感激的。
感谢您花时间阅读这篇文章。如果您觉得它有用,请点赞 ❤️ 或 🦄,分享并评论。
文章来源:https://dev.to/prototyp/optimizing-images-for-the-web-an-in-deep-guide-4j7d