避免使用有损编解码器重新压缩图像
建议始终从原始图像压缩。 重新压缩图像有后果。 假设您使用了已经被压缩的质量为60的JPEG。如果您使用有损编码重新压缩此图像,则会变得更糟。 每轮新一轮的压缩都会引入分代丢失 - 信息将会丢失,并且压缩伪像将开始建立。 即使您正在以高质量设置重新压缩。
为了避免这个陷阱,首先设置你愿意接受的最低质量,从一开始你就可以节省最多的文件。 然后避免这种陷阱,因为任何文件大小的降低都会降低质量。
对有损文件进行重新编码几乎总会给你一个更小的文件,但这并不意味着你可以想象得到更多的质量。
我们可以看到使用多种格式对再压缩造成的世代性损失的影响。 如果从社交网络上保存(已压缩)的图像并重新上传(导致再压缩),这可能会遇到问题。 质量损失将会增加。
编辑源文件时,请将其存储为像PNG或TIFF这样的无损格式,以便尽可能保持质量。 您的构建工具或图像压缩服务比将输出的压缩版本以最小的质量损失输出给用户
减少不必要的图像解码和调整成本
我们都发送了大量的,更高分辨率的图像,而不是我们以前用户需要的。 这是有成本的。 解码和调整图像大小对于普通移动硬件上的浏览器来说是昂贵的操作。 如果发送大图像并使用CSS或宽度/高度属性重新缩放,则可能会看到这种情况,并且会影响性能
当浏览器获取图像时,必须将图像从原始源格式(如JPEG)解码到内存中的位图。 通常图像需要调整大小(例如,宽度已经设置为其容器的百分比)。 解码和调整图像的大小是昂贵的,可以延迟显示图像需要多长时间。
发送浏览器可以呈现的图像而不需要调整大小是理想的。 所以,为您的目标屏幕尺寸和分辨率提供最小的图像,利用srcset和大小 - 我们很快就会介绍srcset。
忽略图像上的宽度或高度属性也会对性能产生负面影响。 如果没有它们,浏览器会为该图像分配一个较小的占位符区域,直到有足够的字节才能知道正确的尺寸。 此时,文档布局必须更新,这可能是一个昂贵的步骤,称为回流。
浏览器必须经过多个步骤才能在屏幕上绘制图像。 除了获取它们之外,图像需要被解码并且经常调整大小。 这些事件可以在Chrome DevTools时间轴中审核。
较大的图像也伴随着内存大小成本的增加。 解码图像是每个像素〜4个字节。 如果你不小心,你可以从字面上崩溃的浏览器; 在低端设备上,启动内存交换并不需要太多的工作。 因此,请注意您的图像解码,调整大小和内存成本。
在平均和低端手机上解码图像的成本可能会非常高。在某些情况下,解码速度可能会慢5倍(如果不是更长)。
在构建新的移动网络体验时,Twitter通过确保为用户提供适当大小的图像,改善了图像解码性能。 这将Twitter时间线上的许多图像的解码时间从〜400ms一直降低到〜19ms!
使用srcset提供HiDPI图像
用户可能通过一系列具有高分辨率屏幕的移动和桌面设备访问您的网站。 设备像素比率(DPR)(也称为“CSS像素比率”)决定CSS如何解释设备的屏幕分辨率。 DPR是由手机制造商创造的,可以提高手机屏幕的分辨率和清晰度,而不会使元素显得太小。
为了匹配用户可能期望的图像质量,将最合适的分辨率图像提供给他们的设备。 可以向支持它们的设备提供清晰的高DPR图像(例如2x,3x)。 低分辨率和标准DPR图像应该提供给没有高分辨率屏幕的用户,因为这样的2x +图像通常会占据更多的字节。
设备像素比例:许多网站追踪流行设备的DPR,包括material.io和mydevice.io。
srcset允许浏览器为每个设备选择最佳的可用图像,例如,为2x移动显示选择2x图像。没有srcset支持的浏览器可以回退到<img>
标签中指定的默认src。
<img srcset="paul-irish-320w.jpg,
paul-irish-640w.jpg 2x,
paul-irish-960w.jpg 3x"
src="paul-irish-960w.jpg" alt="Paul Irish cameo">
一个友好的提醒,客户端提示也可以提供一个替代指定每个可能的像素密度和格式在你的响应式图像标记。 而是将这些信息附加到HTTP请求中,以便Web服务器可以选择最适合当前设备的屏幕密度。
Art direction
尽管向用户发送正确的解决方案很重要,但有些网站也需要从艺术方向来考虑这一点。 如果用户在较小的屏幕上,则可能需要裁剪或放大并显示主题以充分利用可用空间。
Image spriting
在网络上拥有悠久历史的图像精灵(或者CSS精灵)受到所有浏览器的支持,并且已经成为减少页面加载的图像数量的一种流行方式,通过将它们结合成一张切片的更大的图像。
在HTTP / 1.x下,一些开发者使用spriting来减少HTTP请求。 这带来了许多好处,但是,当您快速遇到缓存失效的挑战时,需要小心谨慎 - 对图像精灵的任何小部分的更改都会使用户缓存中的整个图像无效。
而现在可能是HTTP/2的一个反模式。 对于HTTP/2,最好加载单个图像,因为单个连接中的多个请求现在是可能的。
延迟加载非关键图像
延迟加载是一种Web性能模式,可延迟浏览器中的图像加载,直到用户需要查看它为止。 一个例子是,当您滚动时,图像按需加载异步。 这可以进一步补充您从图像压缩策略中看到的字节节省。
不要将它用于主要图像。
如何实现延迟加载
有许多技术和插件可用于延迟加载。我推荐Alexander Farkas的lazysizes,因为它的体面性能,功能,与Intersection Observer的可选集成以及对插件的支持。
Lazysizes是一个JavaScript库。它不需要配置。下载缩小的js文件并将其包含在您的网页中。
将类“lazyload”与data-src和/或data-srcset属性一起使用到图像/ iframe中。
<!-- non-responsive: -->
<img data-src="image.jpg" class="lazyload" />
<!-- responsive example with automatic sizes calculation: -->
<img
data-sizes="auto"
data-src="image2.jpg"
data-srcset="image1.jpg 300w,
image2.jpg 600w,
image3.jpg 900w" class="lazyload" />
<!-- iframe example -->
<iframe frameborder="0"
class="lazyload"
allowfullscreen=""
data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>
避免显示:display:none陷阱
较早的响应式图像解决方案错误地设置CSS显示属性时,浏览器如何处理图像请求。 这可能会导致要求的图像数量比您预期的要多得多,这也是装载响应图像的首选<picture>和<img srcset>
的原因。
你有没有写过一个媒体查询设置图像显示:在某些断点没有?
img src="img.jpg">
<style>
@media (max-width: 640px) {
img {
display: none;
}
}
</style>
或者使用显示切换隐藏的图像:none class?
<style>
.hidden {
display: none;
}
</style>
<img src="img.jpg">
<img src=“img-hidden.jpg" class="hidden">
对Chrome DevTools网络面板进行快速检查,将验证使用这些方法隐藏的图像仍然会被抓取,即使我们预计它们不是。根据嵌入式资源规范,此行为实际上是正确的。
display:none没有可以避免触发图像src的请求吗?
<div style="display:none"><img src="img.jpg"></div>
没有。指定的图像仍然会被请求。一个库不能依赖显示:这里没有,因为在JavaScript可以改变src之前,图像将被请求
display:none没有可以避免触发一个背景的请求:url()吗?
<div style="display:none">
<div style="background: url(img.jpg)"></div>
</div>
<p data-line="144" class="sync-line" style="margin:0;"></p>
是。 一旦元素被解析,CSS背景就不会被获取。 使用display:none为元素的子元素计算CSS样式将不太有用,因为它们不会影响文档的呈现。 子元素上的背景图像不计算也不下载。
再次强调:在可能的情况下,使用<picture>和<img srcset>
,而不是依靠display:none。
缓存图像资产
资源可以使用HTTP缓存头指定缓存策略。 具体来说,缓存控制可以定义谁可以缓存响应和多长时间
您交付给用户的大多数图像都是静态资产,将来不会改变。 这种资产的最佳缓存策略是积极的缓存。
在设置HTTP缓存头时,设置一年的最大年限(例如Cache-Control:public; max-age = 31536000)的Cache-Control。 这种积极的缓存类型适用于大多数类型的图像,特别是头像等。
预先加载关键图片资源
关键的图片资源可以使用·<link rel = preload>
进行预加载。
<link rel = preload>
是声明式读取,允许您强制浏览器在不阻止文档onload事件的情况下请求资源。 它可以提高资源请求的优先级,否则在文档解析过程的后期可能不会被发现。
可以通过指定图像的值来预加载图像:
link rel="preload" as="image" href="logo.jpg"/>
<img>,<picture>,
srcset和SVGs的图像资源都可以利用这个优化。
注意:在Chrome和基于Blink的浏览器(如Opera,Safari Tech Preview)中支持并已在Firefox中实现。
像飞利浦,FlipKart和施乐公司这样的网站使用<link rel = preload>
来预载他们的主徽标资产(通常在文档的早期使用)。 Kayak也使用预加载,以确保他们的主页形象尽快加载。
什么是链接预加载头?
预加载链接可以使用HTML标记或HTTP链接标题指定。 无论哪种情况,预加载链接都会指示浏览器开始将资源加载到内存缓存中,指示页面高度置信地期望使用该资源,并且不希望等待预加载扫描程序或分析程序发现它。
图像的链接预加载标题看起来类似于:
Link: https://example.com/logo-hires.jpg; rel=preload; as=image
使用此优化时应该考虑哪些?
非常确定,值得预先加载图片资源对用户体验是至关重要的话。 通过优先处理图像请求,您可能最终将其他资源推入队列中。
避免使用rel = preload预加载图像格式而不支持广泛的浏览器(例如WebP)是非常重要的。 避免将其用于在srcset中定义的响应图像也很好,其中检索到的源可能会根据设备条件而变化。
总结
最终,选择一个图像优化策略将归结为您向用户提供的图像类型,您决定的是一套合理的评估标准。 它可能是使用SSIM或Butteraugli,或者如果是足够小的一组图像,则脱离人类感知最有意义的东西。