使用 WebP 图片

Avatar of Jeremy Wagner
Jeremy Wagner

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费积分!

我们都经历过:您浏览一个网站,上面有很多美味食物的大图片,或者可能是您一直关注的新奇玩意。这些图片会吸引您的感官,对于内容作者来说,它们是促使人们采取行动的必要手段。

除了这些图片确实很大。非常大。在摇摇欲坠的移动网络连接下,您甚至可以看到这些图片像下降的百叶窗一样在您面前展开。您突然想起拨号上网的旧时光。

这是一个问题,因为图片占典型网站下载内容的很大一部分,而且有充分的理由。图片是富有表现力的工具,它们有能力比文字更能表达。挑战在于如何在视觉丰富的内容和内容的快速交付之间取得平衡。

解决这个问题的方法不是单一的。许多技术可以用来瘦身难以控制的图片,并根据请求它们的设备的能力来交付它们。这样一个主题很容易成为一本单独的书,但这篇文章的重点将非常具体:Google 的 WebP 图片格式,以及如何利用它来提供拥有您现在所有图片的视觉保真度的图片,但文件大小只有一小部分。让我们开始吧!

什么是 WebP,我为什么要关心它?

WebP 是一种图片格式,由 Google 开发并于 2010 年首次发布。它支持对图片进行无损和有损编码,使其成为任何类型视觉媒体的通用格式,以及 PNG 或 JPEG 的绝佳替代格式。WebP 的视觉质量通常与更普遍的格式相当。以下是损失 WebP 图片和 JPEG 图片的比较

你能看出区别吗?(提示:WebP 版本在右边。)

在上面的示例中,视觉差异几乎不可察觉,但文件大小差异却很大。左边的 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 有损配置对话框

有损 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) 安装 imageminimagemin-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 的文件夹中。如果不是这种情况,您可以更改 PNGImagesJPEGImages 变量的值。此脚本还假设您希望 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>元素中

  1. 当浏览器支持 WebP 时,将添加webp类。
  2. 当浏览器不支持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 确实被关闭,那么该类将不会被删除,并将使用更兼容的图片格式。

现在我们已经完成了所有这些,我们可以预期的用例如下

  1. 可以使用 WebP 的用户将获得 WebP。
  2. 那些不能使用 WebP 的用户将获得 PNG 或 JPEG 图片。
  3. 禁用 JavaScript 的用户将获得 PNG 或 JPEG 图片。

给自己鼓掌。您刚刚学会了如何逐步使用 WebP 图片。

结束语

WebP 是一种通用的图片格式,我们可以用它来代替 PNG 和 JPEG 图片(如果支持)。它可以显着缩减您网站上图片的大小,而且我们知道,任何能减少数据传输量的事情都能缩短页面加载时间。

有缺点吗?有一些。最大的一个问题是您需要维护两组图片才能获得最佳支持,如果您的网站有大量图片需要转换为 WebP,这可能是不可能的。另一个问题是,如果您需要在 CSS 中使用 WebP 图片,您将不得不管理一些 JavaScript。另一个值得注意的问题是,将图片保存到磁盘的用户可能没有设置默认程序来查看 WebP 图片。

关键在于,相对较低的工作量是值得您节省下来的,这些节省将通过让网站加载速度更快来改善用户体验。通过移动网络浏览的用户将尤其受益。现在,您可以放心地使用 WebP 了!


Cover of Web Performance in Action

 

Jeremy Wagner 是 Manning Publications 的即将出版的《Web 性能实战》的作者。使用优惠券代码csstripc即可享受 38% 的折扣,或其他任何 Manning 图书。

在 Twitter 上关注他:@malchata