我们都经历过:您浏览一个网站,上面有很多美味食物的大图片,或者可能是您一直关注的新奇玩意。这些图片会吸引您的感官,对于内容作者来说,它们是促使人们采取行动的必要手段。
除了这些图片确实很大。非常大。在摇摇欲坠的移动网络连接下,您甚至可以看到这些图片像下降的百叶窗一样在您面前展开。您突然想起拨号上网的旧时光。
这是一个问题,因为图片占典型网站下载内容的很大一部分,而且有充分的理由。图片是富有表现力的工具,它们有能力比文字更能表达。挑战在于如何在视觉丰富的内容和内容的快速交付之间取得平衡。
解决这个问题的方法不是单一的。许多技术可以用来瘦身难以控制的图片,并根据请求它们的设备的能力来交付它们。这样一个主题很容易成为一本单独的书,但这篇文章的重点将非常具体:Google 的 WebP 图片格式,以及如何利用它来提供拥有您现在所有图片的视觉保真度的图片,但文件大小只有一小部分。让我们开始吧!
什么是 WebP,我为什么要关心它?
WebP 是一种图片格式,由 Google 开发并于 2010 年首次发布。它支持对图片进行无损和有损编码,使其成为任何类型视觉媒体的通用格式,以及 PNG 或 JPEG 的绝佳替代格式。WebP 的视觉质量通常与更普遍的格式相当。以下是损失 WebP 图片和 JPEG 图片的比较

在上面的示例中,视觉差异几乎不可察觉,但文件大小差异却很大。左边的 JPEG 版本重 56.7 KB,右边的 WebP 版本几乎小三分之一,只有 38 KB。还不错,尤其是考虑到两个版本之间的视觉质量相当。
所以下一个问题当然就是“浏览器支持情况如何?”可能不像您想象的那么糟糕。由于 WebP 是 Google 的技术,因此对其的支持固定在基于 Blink 的浏览器上。然而,这些浏览器占全球用户的很大一部分,这意味着在撰写本文时,近 70% 的浏览器支持 WebP。如果您有机会让您的网站为超过三分之二的用户更快,您会放弃它吗?我想不会。
不过,请记住,WebP 不是 JPEG 和 PNG 图片的替代品。它是一种您可以提供给可以使用的浏览器的格式,但您应该为其他浏览器保留旧的图片格式。这就是为网络开发的本质:为能够处理它的浏览器准备您的 A 计划,并为那些能力较差的浏览器准备您的 B 计划(以及可能还有 C 计划)。
免责声明就到此为止。让我们来优化吧!
将您的图片转换为 WebP
如果您熟悉 Photoshop,那么体验 WebP 的最简单方法是尝试一下 WebP Photoshop 插件。安装完成后,您就可以使用另存为选项(而不是“存储为 Web”!)并从格式下拉列表中选择 WebP 或 WebP 无损。
两者有什么区别?将其视为类似于 JPEG 和 PNG 图片之间的区别。JPEG 是有损的,PNG 图片是无损的。当您想要转换 JPEG 图片时,请使用普通 WebP。当您转换 PNG 图片时,请使用 WebP 无损。
当您使用 Photoshop 插件以 WebP 无损格式保存图片时,不会有任何提示。它会自动处理所有事情。但是,当您为有损图片选择普通 WebP 时,您会看到类似下面的内容

有损 WebP 的设置对话框提供了更多灵活性来配置输出。您可以使用 0 到 100 的滑块来调整图片质量(类似于 JPEG),设置过滤配置文件的强度以获得更小的文件大小(当然是以牺牲视觉质量为代价),并调整噪声过滤和锐化。
我对 WebP Photoshop 插件有两个不满:它没有“存储为 Web”界面,这样您就可以预览使用所选设置后图片的外观。如果您想要保存一堆图片,您需要创建一个批处理。我的第二个不满可能对于喜欢在 Photoshop 中进行批处理的人来说不是什么障碍,但我更像是一个程序员,所以我更喜欢使用 Node 之类的东西一次转换多个图片。
使用 Node 将图片转换为 WebP
Node.js 太棒了,对于像我这样的多面手类型来说,它不仅仅是将 JavaScript 带到服务器,更重要的是它是一个我在构建网站时可以使用的生产力工具。在这篇文章中,我们将使用 Node,借助名为 imagemin
的 Node 包,将 JPEG 和 PNG 图片大量转换为 WebP 图片。
imagemin
是 Node 中的图像处理瑞士军刀,但我们只关注使用它将所有 JPEG 和 PNG 图片转换为 WebP 图片。别担心!即使您以前从未使用过 Node,本文也会引导您完成所有操作。如果您不喜欢使用 Node 的想法,您可以使用 WebP Photoshop 插件并跳过此部分。
您要做的第一件事是 下载并安装 Node.js。这应该只需要几分钟。安装完成后,打开一个终端窗口,并转到您的 Web 项目的根文件夹。从那里开始,只需使用 Node 包管理器 (npm) 安装 imagemin
和 imagemin-webp
插件
npm install imagemin imagemin-webp
安装可能需要一分钟。完成后,打开您的文本编辑器,并在您的 Web 项目的根文件夹中创建一个名为 webp.js
的新文件。
将下面的脚本输入到文件中(由 Luke Berry 更新以适应现代 node)
编辑:这两个代码段都适用于 imagemin-webp
的早期版本。最近,此工具已更新为 在 7.0 中使用原生 ESM。请参阅 README 以获取实现方法。您可能需要用 import
替换 require()
。并在您的 package.json
中指定 type: module
。
原始脚本
var imagemin = require("imagemin"), // The imagemin module.
webp = require("imagemin-webp"), // imagemin's WebP plugin.
outputFolder = "./img", // Output folder
PNGImages = "./img/*.png", // PNG images
JPEGImages = "./img/*.jpg"; // JPEG images
imagemin([PNGImages], outputFolder, {
plugins: [webp({
lossless: true // Losslessly encode images
})]
});
imagemin([JPEGImages], outputFolder, {
plugins: [webp({
quality: 65 // Quality setting from 0 to 100
})]
});
const imagemin = require('imagemin'),
webp = require('imagemin-webp')
const outputFolder = './images/webp'
const produceWebP = async () => {
await imagemin(['images/*.png'], {
destination: outputFolder,
plugins: [
webp({
lossless: true
})
]
})
console.log('PNGs processed')
await imagemin(['images/*.{jpg,jpeg}'], {
destination: outputFolder,
plugins: [
webp({
quality: 65
})
]
})
console.log('JPGs and JPEGs processed')
}
produceWebP()
此脚本将处理 img
文件夹中的所有 JPEG 和 PNG 图片,并将它们转换为 WebP。转换 PNG 图片时,我们将 lossless
选项设置为 true
。转换 JPEG 图片时,我们将 quality
选项设置为 65
。您可以随意尝试这些设置以获得不同的结果。您可以在 imagemin-webp
插件页面 上尝试更多设置。
此脚本假设所有 JPEG 和 PNG 图片都在一个名为 img
的文件夹中。如果不是这种情况,您可以更改 PNGImages
和 JPEGImages
变量的值。此脚本还假设您希望 WebP 输出到 img
文件夹中。如果您不想要这样,请将 outputFolder
变量的值更改为您的需求。准备好后,像这样运行脚本
node webp.js
这将处理所有图片,并将它们的 WebP 版本转储到 img
文件夹中。您实现的好处将取决于您转换的图片。在我的情况下,一个包含 JPEG 的文件夹总共约为 2.75 MB,在没有明显的视觉质量损失的情况下被缩减到 1.04 MB。这相当于减少了 62%,而且没有太多努力!现在所有图片都已转换,您就可以开始使用它们了。让我们跳进去,开始使用它们吧!
在 HTML 中使用 WebP
在 HTML 中使用 WebP 图片就像使用任何其他类型的图片一样,对吧?只要将它放到
标签的 src
属性中,就可以了!
<!-- Nothing possibly can go wrong with this, right? -->
<img src="img/myAwesomeWebPImage.webp" alt="WebP rules.">
这将非常有效,但只适用于支持它的浏览器。那些只使用 WebP 的不幸用户访问您的网站时,真是太糟糕了

这很糟糕,没错,但这就是前端开发的现状,所以振作起来。有些功能在某些浏览器中无法正常工作,而且这种情况在短时间内不会改变。我们能使它正常工作的最简单方法是使用
元素来指定一组回退,如下所示
<picture>
<source srcset="img/awesomeWebPImage.webp" type="image/webp">
<source srcset="img/creakyOldJPEG.jpg" type="image/jpeg">
<img src="img/creakyOldJPEG.jpg" alt="Alt Text!">
</picture>
这可能是您获得最广泛兼容性的最佳选择,因为它将在所有浏览器中都能正常工作,而不仅仅是那些支持该元素的浏览器。这是因为不支持该元素的浏览器将只显示在标签中指定的任何源。如果您需要完全支持,您可以随时使用Scott Jehl 的超级流畅的 Picturefill 脚本。
在 CSS 中使用 WebP 图片
当您需要在 CSS 中使用 WebP 图片时,情况会变得更加复杂。与 HTML 中的
元素不同,该元素会在所有浏览器中优雅地回退到
元素,CSS 并没有提供一个最佳的内置解决方案来实现回退图片。像多个背景这样的解决方案最终会在某些情况下下载两种资源,这对优化来说是一个很大的问题。解决方案在于特性检测。
Modernizr 是一个著名的特性检测库,它检测浏览器中可用的特性。WebP 支持恰好是其中一项检测。更棒的是,您可以在https://modernizr.com/download 上进行自定义 Modernizr 构建,只使用 WebP 检测,这样就可以用非常低的开销来检测 WebP 支持。
当您通过<script>
标签将此自定义构建添加到您的网站时,它会自动将两个类之一添加到<html>
元素中
- 当浏览器支持 WebP 时,将添加
webp
类。 - 当浏览器不支持WebP 时,将添加
no-webp
类。
有了这些类,您将能够使用 CSS 根据浏览器的功能加载背景图片,方法是将该元素上的类作为目标
.no-webp .elementWithBackgroundImage {
background-image: url("image.jpg");
}
.webp .elementWithBackgroundImage{
background-image: url("image.webp");
}
就是这样。可以使用 WebP 的浏览器将获得 WebP。那些不能使用的浏览器只会回退到支持的图片类型。双赢!除了...
禁用 JavaScript 的用户怎么办?
如果您依赖 Modernizr,您必须考虑那些禁用了 JavaScript 的用户。抱歉,但这是事实。如果您要使用可能使部分用户无法正常访问的特性检测,则需要在禁用 JavaScript 的情况下进行测试。使用上面提到的特性检测类,没有 JavaScript 的浏览器甚至不会显示背景图片。这是因为禁用的脚本永远不会将检测类添加到<html>
元素中。
为了解决这个问题,我们将首先在<html>
标签中添加一个no-js
类
<html class="no-js">
然后我们将编写一小段内联脚本,并将它放在所有其他脚本之前
<script>
document.documentElement.classList.remove("no-js");
</script>
这将删除<html>
元素中解析时的no-js
类。
这有什么用呢?当 JavaScript 被禁用时,这段小脚本永远不会运行,因此no-js
类将保留在该元素上。这意味着我们可以添加另一条规则来提供支持范围最广的图片类型
.no-js .elementWithBackgroundImage {
background-image: url("image.jpg");
}
这涵盖了我们所有的方面。如果 JavaScript 可用,内联脚本将在 CSS 解析之前运行并删除no-js
类,因此 JPEG 永远不会在支持 WebP 的浏览器中下载。如果 JavaScript 确实被关闭,那么该类将不会被删除,并将使用更兼容的图片格式。
现在我们已经完成了所有这些,我们可以预期的用例如下
- 可以使用 WebP 的用户将获得 WebP。
- 那些不能使用 WebP 的用户将获得 PNG 或 JPEG 图片。
- 禁用 JavaScript 的用户将获得 PNG 或 JPEG 图片。
给自己鼓掌。您刚刚学会了如何逐步使用 WebP 图片。
结束语
WebP 是一种通用的图片格式,我们可以用它来代替 PNG 和 JPEG 图片(如果支持)。它可以显着缩减您网站上图片的大小,而且我们知道,任何能减少数据传输量的事情都能缩短页面加载时间。
有缺点吗?有一些。最大的一个问题是您需要维护两组图片才能获得最佳支持,如果您的网站有大量图片需要转换为 WebP,这可能是不可能的。另一个问题是,如果您需要在 CSS 中使用 WebP 图片,您将不得不管理一些 JavaScript。另一个值得注意的问题是,将图片保存到磁盘的用户可能没有设置默认程序来查看 WebP 图片。
关键在于,相对较低的工作量是值得您节省下来的,这些节省将通过让网站加载速度更快来改善用户体验。通过移动网络浏览的用户将尤其受益。现在,您可以放心地使用 WebP 了!
难道不能使用 @support 来覆盖默认的背景图片,用 webp 图片来代替,而不是依赖于 modernizr 吗?
或者它会认为它得到了支持,只是忽略了 url() 中提供的图片?
不,@supports 只能检查 CSS 引擎是否支持给定的属性/值对(在某些情况下,甚至会撒谎)。
当我尝试使用多个背景技巧时,我相信它最终还是会下载 WebP 源代码——然后失败。所以从某种程度上来说,这是不理想的。我得回去查看一下,但我记得在 4 月份在我的博客上第一次写这篇文章的时候,我并没有选择这条路,这是有特定原因的。
感谢阅读!
还要确保 HTTP 服务器支持 webp 图片,并正确发送 image/webp 作为内容类型。
我曾经快乐地使用 webp 图片开发了一个面向 Blink 浏览器,但当我把它发布到线上时却看不到任何东西,因为它们被作为 application/octet-stream 传输
是的!我自己还没有遇到过这个问题,但有些配置可能需要这样做。如果您需要在 Apache 中以某种方式做到这一点,以下操作应该有效
感谢您提出这个问题!:)
完全公开:我写的!
这是如何使用 Nginx 向 Microsoft Edge 提供 Webp 和 JXR 图片。以及如何通过 Photoshop 或命令行转换为 jxr
它使用内容协商,因此您可以继续使用带有或不带有 srcset 的常规图片标签,并且提供了 Ilya Grigorik 和 Eugene Lazutkin 提出的用于 Webp 图片的原始解决方案,适用于 Apache 和 Nginx!
如果有帮助的话,我编写了一个 WordPress 插件,在上传时处理图片到 WebP 的转换。它不会使前端加载这些图片,您需要在您的主题中完成,但它会转换所有图片,包括自定义图片大小。
https://github.com/randyjensen/rj-webp-converter
非常有用!但要注意正则表达式;它们可能有点棘手。您应该将
/(.jpg|.png)/
的实例重写为/\.(jpe?g|png)$/i
— 一个
.
只意味着“任何东西”,不一定是点;您需要使用反斜杠将其改为字面意思—
jpe?g
将匹配jpg
和jpeg
—
$
确保匹配只在末尾(否则jpgofacat.jpg
在运行preg_replace
时会变成ofacat.web
)— 末尾的
i
使其不区分大小写我还建议您查看 PHP 的原生 WebP 功能:https://php.ac.cn/manual/en/function.imagecreatefromwebp.php 它们可能不像从服务器运行
cwebp
那样快,但exec()
是一个非常危险的 PHP 函数,应该禁用,因此任何可以消除该依赖的机会都值得尝试。Josh 提出的观点非常好。谢谢!
我已经两年多没有更新这个插件了,所以我认为现在是一个重新审视它的好时机。
别乱说,我认为您可以通过设置
open_basedir
php.ini 指令来限制对系统中其他文件夹的访问权限:https://php.ac.cn/manual/en/ini.core.php#ini.open-basedir因此,如果您设置了它,您可能仍然可以安全地使用
exec
或shell_exec
,但不要相信我的话,自己测试一下。不过,我仍然在我的配置中禁用了这两个函数。是的,exec 绝对需要被移除。看起来 https://php.ac.cn/manual/en/function.imagewebp.php 正是我需要的。这将允许我摆脱 libwebp 依赖关系,并将插件加入官方 WordPress 仓库。这就是你不碰一个库两年会发生的事情。
open_basedir
限制只适用于 PHP。exec()
发生在 PHP 外部(这就是它很危险的原因)。这些命令受文件系统施加的常规 r/w/x 权限限制,但仅此而已。将 PHP 和系统结合在一起的更好方法是
proc
函数族(例如 https://php.ac.cn/manual/en/function.proc-open.php)。在这里,PHP 实际上负责启动和管理特定的系统进程,因此open_basedir
限制将适用。与其将整个/usr/bin/
或类似的疯狂的东西列入白名单,你可以添加单个二进制文件,例如/usr/bin/gpg
。proc
是单个项目或 PEAR/PECL 包的最佳解决方案,但对于通用 WordPress 函数来说有点太复杂了。在这种情况下,原生 PHP 可能是你所能获得的全部。 :)嗨 Jeremy - 你是否有任何数据表明使用 webp 可以减少页面加载时间?我不会在没有广泛测试的情况下假设它能做到。webp 的解码速度比 jpeg 慢得多,因此图像更小并不一定意味着你会获得更快的页面加载速度。网页不是一个统一的数据块,它以统一的速度解码和渲染。这些都是完全不同的格式,具有不同的编解码器。我试图从 Google 获取真实的 webp 性能数据,但到目前为止,他们还没有发布任何数据。在没有详细的性能数据显示出益处的情况下,使用 webp 没有太多意义,除非目标只是为了减少带宽费用,而不管页面性能如何。
解码时间微不足道。凭借现代处理能力,没有理由认为解码任何图像,即使是 WebP 图像,也会花费很长时间,以至于显着减少通过网络传输的数据量会成为无用的努力。
我在我的书中写过关于这个问题的内容,通过一个例子,我能够将加载时间减少约 20%-35%,具体取决于所涉及屏幕的 DPI。如果你对本章感兴趣,我可以免费寄给你一份,直接在我的 Twitter 帐户上给我发私信即可。如果你做不到,告诉我你的用户名。我会关注你,以便你与我联系。
在这种情况下,获取真实世界性能数据的最佳方法是创建自己的数据。我在我的博客中为所有栅格图像使用 WebP,如果我不认为它对性能有益,我永远不会向任何人推荐它。对现有内容来说,它的实现是否很耗时?当然。但我认为,如果你能证明它的价值,结果是值得的努力的。
感谢阅读!
Jeremy,这部分看起来不对
“解码时间微不足道。凭借现代处理能力,没有理由认为解码任何图像,即使是 WebP 图像,也会花费很长时间,以至于显着减少通过网络传输的数据量会成为无用的努力。”
如果我理解正确,你是在说解码速度慢无法抵消较小的文件大小,从而在下载时间 + 解码/光栅化时间总时间上体现出来?这对于各种格式和场景来说肯定是不正确的。如果这是一个普遍的观点,我们需要教育人们。基本数学将与 Cloudflare 在分析 brotli 时发布的内容类似:https://blog.cloudflare.com/results-experimenting-brotli/
如果我们关注的是客户端,那么数学就是下载时间 + 解码时间。如果基线是 100 KiB JPEG,解码需要 10 毫秒,在 10 Mibit/sec 连接上,则下载需要 80 毫秒,解码需要 10 毫秒,总共需要 90 毫秒。
如果我们改为提供 webp,假设它现在只有 60 KiB,但解码需要 5 倍的时间,那么下载需要 48 毫秒,解码需要 50 毫秒,总共需要 98 毫秒。
这种结果很容易发生在各种编解码器更改中。例如,如果我们从 gzip 切换到 xz(对于所有文本文件),我们将获得更小的下载大小,但更慢的解压缩速度将很容易超过下载节省的效益,这就是我们不这样做的原因。webp 的解码速度比 jpeg 和 png 慢得多。具体慢多少是一个谜,因为 Google 不会发布有效的数据。腾讯报告称,它比 PNG 慢 4 或 5 倍:https://isux.tencent.com/introduction-of-webp.html 请注意,PNG 在几乎所有设备上都比 JPEG 慢(JPEG 基本上是魔法,而且很多设备都有硬件加速的 JPEG 解码,甚至有专门的“固定功能”JPEG 解码芯片。
由于他们正在推广这种格式,而且他们有如此多的资源和资金,我预计 Google 将完全记录 webp 格式,并生成丰富、有效的性能数据。他们拒绝这样做非常奇怪。Webp 甚至没有规范或标准,而且目前存在相当多的错误。将宝贵的资产放到没有规范的格式中存在风险,而且新的解码器版本可能会破坏使用先前版本编码的文件(去年 webp 就发生了这种情况)。Webp 也可能导致页面加载时间变慢 - 它的解码速度慢到抵消了压缩节省的效益。这在他们的有损模式中似乎比在无损模式中更可能发生,但没有人能确定。在 webp 列表中有一个关于这个问题的帖子,我在其中回顾了 Google 试图伪造的“证据”(上面的腾讯研究是他们所有链接中唯一一个性能数据):https://groups.google.com/a/webmproject.org/forum/#!searchin/webp-discuss/useful$20performance$20data/webp-discuss/4r6frraRtkg/nNdTEitlMwAJ
人们不应该仅仅因为 Google 告诉他们就使用某样东西。他们需要提供证据,他们应该停止在网络上贬低 MozJPEG 的行为。他们现在的行为很奇怪(https://blog.cloudflare.com/experimenting-with-mozjpeg-2-0/ https://medium.com/@duhroach/reducing-jpg-file-size-e5b27df3257c#.oj7an6ffs)
以下是我在分析 Chrome 在我使用 WebP 时似乎的行为时发现的,请记住,这只是一个测试用例,绝非详尽无遗。
我在服务器上有两张图片
https://jeremywagner.me/img/global/stpaul-2x.jpg
https://jeremywagner.me/img/global/stpaul-2x.webp
这两张图片都是圣保罗市中心的景色(因为是明尼苏达州)。源文件是一个我在 Google 图片上找到的 JPEG。它的大小为 126 KB,这是在使用 imagemin-jpeg-recompress 处理 JPEG 后的大小。WebP 版本是有损 WebP,质量设置为 65,大小为 59.8 KB。这些数字来自 Chrome 的网络面板,因此它们表面上包括最终大小中的 HTTP 标头。从视觉质量来看,这些图片非常相似。
现在让我们谈谈解码时间。我们可以讨论解码时间以及它有多么微不足道/重要。对我来说,它微不足道。因为一旦我有了备用图像格式,而且我知道它很小,我唯一关心的是浏览器开始绘制图像需要多长时间。使用 Chrome 的时间轴工具,以下是我在使用 Google Chrome 的“良好 3G”网络限速配置文件(1.5Mb/s)对每种图像类型进行十次试验(禁用缓存)时,看到的第一绘制时间:
JPEG:455.85ms
WebP:320.63ms
这大约提高了 30%。当然,这个测试是针对单个图像的,直接在网页之外进行访问。但我认为它是一个相当不错的证明,表明解码时间并不是一个很大的因素。请记住,你的解码时间数据的来源是在 2014 年发布的 - 浏览器的内部结构在两年内可能会发生很大变化。如果这些数字在今天仍然准确,那么随着连接速度变慢,它们的影响会减小。互联网基础设施和连接质量在发展中国家仍然是一个问题。当我测试速度时,我会测试那些连接速度最慢的人可能会受到的影响。因此,我仍然会定期在 2G 和 3G 模拟中进行测试。
WebP 不是万能药。JPEG、GIF、SVG 或 PNG 也不是。我们拥有所有这些不同的格式,它们都适合各种内容。在某些情况下,我将 PNG 无损编码为 WebP,而 WebP 格式实际上更大。在这种情况下,我会丢弃它们,并使用 PNG 图像。不过,大多数时候,当我使用 WebP 时,结果是在明显更小的图像文件下具有可比的图像质量。FWIW,我不为 Google 工作,也不受他们约束。我认为 WebP 是一种非常有竞争力的格式,我将在它有意义的地方推荐它。
在像 CMS 这样的真实世界条件下,WebP 对加载时间的影响非常惊人,因为普通用户不会花任何时间为网络优化图形。我最近更新了一个客户的 WordPress 网站,使其能够自动从他们上传的源文件中生成 WebP 图像,并将所有内容包装在
<picture>
元素中(包括背景,使用object-fit
和 polyfill)。在大约 4000 张现有图像中,混合了 JPEG、PNG 和 GIF,WebP 对等体(仅使用-jpeg_like
标志生成)最终缩小了 59%。(服务器已经对上传的图像进行了无损压缩,JPEG 的平均节省量约为 10-15%,PNG 的平均节省量约为 50-75%;59% 的 WebP 数字是额外节省的)。当然,这会因为额外的
<picture>
标记和object-fit
polyfill 而稍微增加文档大小,但 gzip 和 http/2 优化使得文本变得非常小。由于需要对文件系统进行额外检查以查看 WebP 姊妹图像(尤其是在使用 srcset 时,因为要检查的源文件要多得多),因此还会产生额外的 i/o 负担,导致文档编译时间增加。但即使如此,页面加载最终平均快了约 40%。WebP 节省的效益远远超过了文档膨胀和 i/o,因此页面上的图像越多,节省的效益就越高。还没有人报告任何与解码相关的延迟。我怀疑容易出现这种情况的机器根本就不会运行支持的浏览器。
@Josh
” (服务器已经对上传的图像进行了无损压缩,JPEG 的平均节省量约为 10-15%,PNG 的平均节省量约为 50-75%;59% 的 WebP 数字是额外节省的).”
这句话提出了很多问题。首先,不存在对 JPEG 进行无损压缩的说法。JPEG 总是会丢失信息。即使你打开一个 JPEG 并在不进行任何更改的情况下保存它,它仍然是有损的。我假设你指的是它们被压缩,但没有立即出现视觉质量的损失,但这与无损压缩并不相同。这只是一个“安全”的压缩级别。
如果我继续读下去,我的理解是,接下来你由于使用了 WebP 并且在压缩了 15-20% 的 JPEG 文件基础上,又额外获得了 59% 的节省。 这可以意味着很多事情。
首先,所谓的“无损”压缩的 JPEG 文件可能意味着它们一开始就没有被很好地压缩。 因此,这可能意味着,如果你将 JPEG 质量级别设置为 60-70%(最佳点),你实际上可以节省高达 70% 的文件大小。 在这种情况下,你会将 JPEG 格式推到它的极限。
我不相信你能够在压缩后的基础上额外节省 59%。 WebP 相比于最大可使用压缩的 JPEG 肯定不会带来 59% 的整体节省。 你实际上节省的是一个几乎没有压缩的 JPEG 文件的 59%,这不是一个公平的比较。
我应该修改我的上一条评论,说明无论是生成图像本身还是检查它们是否存在,与 I/O 相关的延迟很大程度上取决于服务器。 我不会在没有一些严肃的缓存的情况下尝试在共享主机上进行任何磁盘或数据库密集型的优化,因为很有可能它已经足够努力地仅仅渲染基本的主题。
@Ferdy,
在这种情况下,JPEG 压缩几乎完全是移除图像的元数据(即非图像位)。 最终用户倾向于直接从相机上传图像,可以说,没有花费任何预上传的努力来制作更适合网络的版本。 元数据当然有它的用途,但对于这个特定的网站,它充其量是膨胀,最坏情况下是安全风险,因此服务器会做用户不做的事情并将其移除。 从这个操作中获得的相对百分比节省取决于元数据与图像数据的比率。 即使是一个喜欢标签的人也无法对高分辨率照片造成很大的相对影响,但一些来自 Getty 的廉价低分辨率库存照片呢? 元数据将占原始文件大小的更大百分比。 我提到的特定网站倾向于上传介于两者之间的图像,因此移除元数据平均节省了约 10-15%。
但你说 JPEG 容器格式没有空间进行无损压缩是错误的。 确实没有多少空间,但毕竟还是有空间的。 有像 jpegrescan 这样的工具可以节省额外的 1-2%。 有时通过将 JPEG 设为渐进式(如果其他什么都没有,它们有更友好的解码显示)也可以进行改进。
关于你的另一条评论,图像一开始没有被很好地压缩,当然,它们没有被很好地压缩。 我们完全一致。 我使用“真实世界条件”来描述真实世界。 平均电脑用户不了解 JPEG 和 PNG 之间的差异,更不用说每个格式中嵌入的配置选项了。 无损压缩只能优化现有内容的编码;它永远无法与从一开始就以适当配置保存图像相提并论。 ;)
因此,重申一下,我帖子中提到的图像是在客户端上传的(加上 CMS 生成的各种缩略图),并且通过自动服务器进程进行了无损清理。 在这种“现实世界”用例中,在
cwebp
二进制文件中使用-jpeg_like
标志产生的文件(这次是有损的)比压缩后的源文件小 59%。 WebP 和源图形看起来并不完全相同。 WebP 在某些类型的纹理上会有一点光泽,如果你并排看到两个版本,你就可以发现。 但这些效果考虑了人类,因此不会以我们可能在没有比较的情况下注意到的方式使用。我无意暗示 WebP 将始终节省 59%,只是它在从更常见的(即糟糕的)源开始时甚至比其他人提到的表现要好。 我在我的一个网站上实施了类似的 WebP 解决方案,但那里的源材料一开始就优化得更好,只有 JPEG,而且图像质量与客户使用的图像不同(半色调过滤的照片内容……对 WebP 和 WebM 优化都是杀手),所以我只节省了大约 10%。 哈哈。
@Josh
59% 对我来说似乎很现实,对于未优化的源图像。
你所说的“无损”,是指像 imagemagick convert 的“ -quality 100”选项吗? 这实际上可能会增加源文件的大小…… 或者更像是“ -quality 75”(没有很大的视觉差异)? (请记住,每个应用程序可能都定义了自己的质量等级,因此“quality 75”的含义在 gimp、photoshop、imagemagick……中是不同的)
@Ferdy
实际上,似乎存在:convert 的“ -quality 0”或“ -quality 100”。 我不太明白它们之间的区别。 100 通常会增加文件大小;0 对我来说似乎是无损的,它会减小高质量图像的文件大小,会增加之前降采样图像的大小( -quality 35);1 是 imagemagick 中 jpg 的最差质量设置。
@Valentin,
不,我不是指 JPEG 的质量设置。 即使最终结果实际上更大(例如从 85 转换为 100),这仍然属于“有损”。 虽然正如我和 @Ferdy 讨论的那样,尝试 JPEG 质量设置是人们为了网络优化可以做出的最重要的单一事情。 但对于 WordPress 来说,源图形的质量设置是没有意义的,因为网站通常只向访问者提供自动生成的缩略图,缩略图以设定的质量保存,并且不会真正从源文件的磁盘大小中继承任何好处。 为 WP 上传优化的源文件的唯一真正好处是它能够更快地生成缩略图。
对于无损 JPEG 压缩,我运行两个程序:jpegoptim 和 jpegrescan。
jpegoptim 去除元数据并使 JPEG 成为渐进式的。 元数据往往是最节省的空间,因为图像程序、相机等等可以在那里注入大量数据。 渐进式也可以节省一些磁盘空间,虽然不总是这样。
jpegrescan 会查找实际压缩中的低效部分,并在可能的情况下进行改进。 它的影响取决于最初保存图像的程序。
好文章,但我确实认为它省略了最重要的部分,即节省与质量。 小型缩略图的例子对 webp 非常有利,确实,大小更小,而且你实际上看不出任何区别。
但是,将其作为应该尽可能地将所有图像都作为 webp 来服务的结论是错误的,这是文章暗示的。
例如,一旦你将目光转向更大的图像尺寸,质量差异就会变得更加明显,尺寸差异也是如此。 WebP 确实倾向于在大型图像中表现出色,但也存在巨大的问题,例如对人物照片的皮肤进行过度平滑处理。
不是直接针对文章的作者,但我读到的关于 webp 大概小 30% 的普遍结论绝对不是一个最低限度,它更像是一个最大限度。 同样,关于它们提供类似质量的结论也取决于实际内容。
因此,在很多情况下,优势远小于 30%,这让我不禁要问……为什么还要费心? 我不是反 WebP,我只是认为它被吹嘘过头了。
WebPJS 发生了什么? https://webpjs.appspot.com/ 它似乎被放弃了。 是否有任何更好的 WebP JavaScript 实现?
@Josh:谢谢,你澄清了很多事情。 因此,重申一下你的流程
用户上传原始文件(带有 exif/meta,通常未压缩)
自动流程移除元数据,节省 15-20%
你运行有损 webp 压缩,额外节省 59%
听起来不错,尤其是在发现输出质量是可以接受的情况下。 但它仍然留下了开放性问题:如果第 3 步是有损 JPEG 压缩会怎么样? 你能节省多少? 会比 59% 多还是少,以及它在不同的压缩级别下会对视觉质量造成什么影响?
你不需要回答这个问题,但我认为这是 webp 与 jpeg 压缩的真正问题。 为了进一步使事情复杂化,内容类型确实也起作用。 :)
为网络正确保存图像是一个好主意,但实际上没有神奇的质量设置;它很大程度上取决于主观的眼睛和图像的内容。 具有鲜明对比色彩的图片即使在 95% 的情况下也可能出现明显的伪像(除非你禁用 chrome 次采样),而沙漠景观在低至 50% 的情况下也可能完全没问题。 在这个特定项目中使用的所有花哨的图像技术都是可以安全地无人监管地进行其工作的技术。
WordPress 在制作缩略图时默认使用 85% 的质量设置。 这对于大多数类型的图片来说似乎是一个相当不错的基线。 大多数主题应该在网站的几乎所有地方使用自定义缩略图大小,在这种情况下,无论用户最初上传了什么,访问者总是可以从有损压缩中获益。
但这种做法似乎被忽略的一个地方是图像必须无限扩展以覆盖某个区域的情况,例如大型英雄。 好的老
background-cover
。 事实上,用响应式object-fit
<picture>
元素替换我客户网站上的 CSS 背景是造成整体页面大小最大影响的原因。 即使没有 WebP 参与其中,情况也会如此,尽管 WebP 使它更进一步。 标记有点烦人,并且 polyfill 必须被重写和测试,但回报是值得的。@Josh.
图像内容绝对决定了你能用哪个质量等级。但在工作中,我们没有逐张图像设置质量等级的条件,因此不得不设置一个全局质量等级。经过对大量图像的广泛测试,我们成功将质量等级降至 60-65%。这个等级正好处于出现伪影的临界点。需要注意的是,这些图像都是人们使用产品的照片。尽管如此,即使是在大型页眉图像上使用这种较低质量等级,也没有引起任何投诉。如果你查看 JPEG 质量等级与文件大小图表,你会发现 60% 非常接近最佳值。需要注意的是,这条曲线并非线性。
因此,我认为 85% 的质量等级非常保守。特别是对于缩略图来说,根据它们的大小,你甚至可以尝试将质量等级降至 60% 以下,因为伪影往往太小,不易察觉。
最后,我想提一下一个被低估的技术。
https://www.netvlies.nl/tips-updates/design-interactie/retina-revolution
这种技术使用非常大的图像(就分辨率而言),然后对其进行非常激进的压缩。接着,它让浏览器对图像进行调整大小。这样一来,在很多情况下,你只需提供一张图像即可满足所有需求,同时支持 Retina 显示,而且不会增加文件大小。这难道不是最好的选择吗?
主要的批评意见是,当这些比实际需要更大的图像在客户端解码时,会导致内存使用量增加。但实际上,我已经使用这种技术几年了,它在我的一个网站上没有任何实际问题。
如何使用 Google Pagespeed 模块仅在浏览器支持的情况下才转换为 WebP 格式?:)
https://developers.google.com/speed/pagespeed/module/filter-image-optimize
@Jeremy 这些数字看起来不错。你说“一旦我有了备用图像格式,并且知道它足够小,我唯一关心的是浏览器开始绘制图像需要多长时间”,这与我关心的也很接近。你将它与解码时间并列,但我认为应该将所有这些因素都考虑在内,所以应该明确这一点。
对我来说,底线是页面渲染时间,包括我们需要渲染的任何图像。因此,我对你这个指标的唯一异议是,我不太关心浏览器开始绘制图像需要多长时间,而是更关心它完成渲染所有图像和整个页面需要多长时间。两者可能是互为代理的 - 我不确定。
腾讯数据来自 2014 年,但 Google 数据更早 - 4 到 5 年。我困惑的是,为什么 Google 不发布任何有效的数据,当我要求提供数据时,他们试图用一些 CDN 吹嘘文章来蒙混过关,这些文章只谈论文件大小,这让我感到震惊,所以我可能对他们心存偏见。WebP 也让我感到不安,因为它没有规范,而且 Google 的开发和测试过程显得随意且缺乏系统性 - 错误随机出现,他们没有发布包含良好测试图像的自动化测试套件。更广泛地说,他们的项目通常只关注 Mac,最终导致他们在 Windows 机器上测试不足,所以我预计 WebP 和 Windows 会出现意外情况。他们的有损转换过程和 API 文档如此糟糕,让我对将资产转换为 WebP 犹豫不决,即使 JPEG 和 TIFF 应该仍然存在 - 我不喜欢使用格式不稳定的资产。
适当的怀疑是好事,我知道这篇文章是支持 WebP 的,但我之所以这样说,是因为我在应用 WebP 时取得了成功。如果 WebP 图像比其等效的 JPEG 或 PNG 文件大小明显更小,它将在传统格式加载之前开始绘制,在我看来,这抵消了解码方面的任何劣势。这在非常缓慢的连接(例如发展中国家的连接)中尤其如此。说到数据计划受限的互联网用户,WebP 可以成为他们的宝贵资产,因此速度并不一定是我们唯一需要考虑的方面。
我同意 Google 应该提供有关其性能的官方指标,但另一方面,这种格式也是公开的,任何人都可以使用。任何愿意尝试的人都可以得出自己的结论,前提是他们具备严格测试的知识和能力(我坦率地承认,这可能是经验不足的开发人员的一道障碍)。对于 Windows,我还没有遇到任何与 WebP 相关的问题。我在家使用 MacBook Pro 进行我的副业项目开发,在工作中使用 Windows 机器,因此我每天都能在两种环境之间取得平衡。
关于这一点,libwebp 也是开源的:https://chromium.googlesource.com/webm/libwebp 从我看到的来看,编码器和解码器的源代码是可以查看的。我不一定相信他们是在故意躲躲闪闪。我平时不写 C 或 C++ 代码,所以我无法解释源代码的每个角落和缝隙,但这并不是说 Google 将 WebP 作为 Soylent Green 提供。更可能的是(至少对我来说),他们同时进行着许多高调的项目,而 WebP 在他们的优先级列表中排名较低。
还有一个 WebP 容器规范,可以在 https://developers.google.com/speed/webp/docs/riff_container 查看,这可能对你有所帮助。如果你已经足够烦扰 Google 了,我想他们应该已经把这个规范发给你了,所以也许这个规范不能满足你的要求。
希望这有帮助。感谢你质疑我的观点。我认为这些来回讨论为文章之外的一些好的阅读提供了素材。:)
-j
@Ferdy JPEG 可以无损压缩。JPEG 是有损格式的事实并不意味着任何给定的 JPEG 无法进行无损压缩(超出其先前的有损压缩或创建)。除了元数据之外,量化表也可以进行优化,这是 MozJPEG 所做的事情之一。通常,它归结为采用现有的编码(它是压缩的)并寻找优化这种编码的方法。
@Josh 根据 Smashing 文章中的数据,I/O 相关的延迟可能是使用 WebP 的最大问题:http://mattshull.com/webptests.pdf
我很惊讶地看到 iPhone 的时间仅仅因为为其他浏览器使用 WebP 而下降。对于 iPhone 来说,没有什么应该改变,因为它在测试 C 和 D 中仍然接收 JPEG(因为 Safari 不支持 WebP)。这可能是 htaccess 相关的延迟。我认为当人们谈论 WebP 和其他改进的压缩格式时,一个重要的问题被忽略了。部署新格式不仅会改变浏览器的行为,还会改变服务器的行为。它会向服务器添加代码、逻辑和复杂性,并可能增加延迟。应该可以消除大部分延迟,但默认情况下,看起来让 Apache 向某些浏览器提供 WebP 文件,而向其他浏览器提供 JPEG 文件,确实减慢了速度。这需要进一步挖掘和研究。
正如你所提到的,JPEG 优化还有很大的空间。对我来说,还不清楚是否不能通过使用更好的 JPEG 工具(如 JPEG-Recompress 和 JPEGMin)来实现 WebP 等效的大小缩减,这两个工具似乎都在使用 smallfry 算法(参见:https://github.com/danielgtaylor/jpeg-archive)
@Jeremy 当我尝试使用 node webp.js 运行 imagemin-webp 插件时,出现以下错误
C:\work\webp\webp.js:7
new imagemin().src(PNGImages).dest(outputFolder).use(webp({
^
TypeError: (input, output, opts) => {
if (!Array.isArray(input)) {
return Promise.reject(new TypeError(‘Expected an arr……
} is not a constructor
at Object. (C:\work\webp\webp.js:7:1)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:974:3
你知道是什么问题吗?
Dave,抱歉!我看到了,但被耽搁了。如果你还没有解决这个问题,请给我发送邮件到 [email protected],或者在 Twitter 上 @malchata 联系我并发送你的代码。我会检查一下。在我看来,这应该是一个简单被忽视的东西。
感谢你的阅读,伙计。:)
嗨,Jeremy。感谢你的文章,它非常棒。我已经在我的项目中使用 WebP 图像了,我发现将 WebP 用作背景会遇到一些问题。例如,我有一个 `header.png` 用于 `no-js` 和 `no-webp` 类,以及一个 `header.webp` 用于 HTML 标签的 `webp` 类。起初我认为图像下载的工作方式与你在文章中描述的一样,但后来我从手机网络查看页面时发现,背景图像下载了两次 - 首先是 PNG 版本,然后是 WebP 版本。我在开发者工具中的网络选项卡中查看,证实了我的怀疑 - 有两个下载的背景图像。PNG 首先开始下载作为 `no-js` 的背景,然后 `webp` 类被添加到 HTML 标签中,WebP 图像再次开始下载。所以,也许有解决方法/另一种方法可以从 CSS 中使用 WebP 作为背景吗?