自动压缩和编码

无缝生成高性能图片来源 开发过程。

在本课程中,我们将介绍从图片数据编码到 为自适应图片提供支持的标记 - 是机器与机器通信的方法。你有 它探索了多种方式,可让客户端浏览器向服务器传达其需求,并让服务器做出相应的响应。 自适应图片标记(特别是 srcsetsizes)在相对较短的时间内 几个字符。不管是好是坏,这种简洁性都是由设计来决定的:使这些语法更简洁,对开发者来说也更容易 可能会加大浏览器解析的难度。字符串越复杂, 则可能会出现解析器错误,或不同浏览器之间行为上的意外差异。

自动图片编码窗口。

然而,由于这些特征会让这些主题变得令人生畏,相同的特质也可以为你提供解决方案:轻松使用语法 机器读取是一种更容易被机器编写的语法。您几乎肯定会遇到过许多 图片编码和压缩:通过社交媒体平台上传到网络的任何图片、内容 管理系统 (CMS),甚至电子邮件客户端几乎总会经过一个能够调整大小、重新编码、 并进行压缩

同样,无论是通过插件、外部库、独立构建流程工具,还是通过负责任地使用客户端脚本, 自适应图片标记可以轻松实现自动化。

这些是图像性能自动化的两个主要问题:管理图像创建,即其编码、 压缩,以及用于填充 srcset 属性以及生成面向用户的标记的其他来源。 在本单元中,您将了解在现代工作流中管理图片的一些常见方法, 自动化阶段(通过为网站提供支持的框架或内容管理系统), 它几乎被专门的内容分发网络所抽象化。

自动压缩和编码

您不大可能处于需要花时间手动确定理想的编码和级别 也不愿意针对要用于项目的每个图片进行压缩。如 尽可能缩减图像传输大小 压缩设置和为每个要用于生产网站的图片资产重新保存备用来源会带来 是日常工作的巨大瓶颈。

正如您在阅读各种图像格式和压缩类型时所了解到的,对图像最有效的编码始终取决于 正如您在自适应图片中所看到的,图片来源所需的备用尺寸将是 取决于这些图片在网页布局中所处的位置。在现代工作流程中,您需要 确定一组合理的默认值,以便更好地适应 预期用途

在为摄影图片目录选择编码时,AVIF 显然在质量和传输大小方面更胜一筹 但支持有限,WebP 可以提供经过优化的新式后备方案,而 JPEG 则是最可靠的默认选项。备用 对于要在页面布局中占据边栏的图片,我们需要为这些图片生成 在我们的最高断点处占据整个浏览器视口。压缩设置需要注意模糊处理 和压缩伪影,从而节省了从每个图片中剥离每个可能字节的空间更少 来换取更加灵活可靠的工作流程。总之,您需要遵循与贵公司相同的决策流程 大型语言模型。

至于处理本身,有大量的开源图像处理库提供 批量转换、修改和编辑图像,在速度、效率和可靠性方面展开竞争。这些处理 库可让您一次性对整个图片目录应用编码和压缩设置, 需要打开图片编辑软件,并且保留原始图片来源(如果这些设置需要的话) 可以随时进行调整它们适合在从本地开发环境到 网络服务器本身,例如,用于计算压缩效果的 ImageMin Node.js 可以通过一系列插件进行扩展,以适应特定的应用。 而跨平台 ImageMagick 和基于 Node.js 的 Sharp 提供了数量惊人的开箱即用功能。

借助这些图像处理库,开发者可以构建专用于无缝优化图像的工具 作为标准开发流程的一部分 - 确保您的项目始终引用可正式投入使用的映像 获得尽可能低的开销

本地开发工具和工作流

Grunt、Gulp 或 Webpack 等任务运行程序和捆绑器可用于 优化图片资源并执行其他常见的性能相关任务,如缩小 CSS 和 JavaScript。接收者 我们来看一个相对简单的用例:项目中的目录包含十几幅摄影图片、 用于面向公众的网站上。

首先,您需要确保对这些图片进行编码一致且高效。正如您在前面的单元中所了解到的, 就质量和文件大小而言,WebP 是一种高效的默认图片处理工具。WebP 得到良好支持 但并非普遍支持,因此您还需要添加渐进式 JPEG 形式的后备图片。然后, 为了利用 srcset 属性高效投放这些资源,您需要生成多个 为每种编码提供备选尺寸

如果使用图片编辑软件完成这项工作,这是一项重复且耗时的工作,但像任务运行程序一样, Gulp 旨在准确自动执行此类重复。gulp-response 使用 Sharp 的插件是一个选项,所有这些插件都遵循类似模式: 收集源目录中的所有文件,对它们重新编码,并根据相同的标准化“质量”对它们进行压缩, 图片格式和压缩中学到的简写形式。生成的文件随后会输出到您定义的路径 以便在面向用户的 img 元素的 src 属性中引用,同时保留原始文件。

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.webp = function() {
  return src('./src-img/*')
    .pipe(respimg({
      '*': [{
        quality: 70,
        format: ['webp', 'jpeg'],
        progressive: true
      }]
  }))
  .pipe(dest('./img/'));
}

通过采用这样的流程,如果项目中的某个人无意中对生产环境造成了损害,将不会对生产环境造成任何危害 向包含您原始图片来源的目录中添加了一张编码为大型 Truecolor PNG 的照片(不管其为 原始图像编码,此任务将产生高效的 WebP 和可靠的渐进式 JPEG 回退, 可以轻松即时调整的压缩级别。当然,这一过程还可以确保 文件将保留在项目的开发环境中,这意味着您可以随时调整这些设置 并仅覆盖自动输出结果

为了输出多个文件,您需要传递多个配置对象,除了添加 width 键和以像素为单位的值:

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.default = function() {
  return src('./src-img/*')
    .pipe(respimg({
    '*': [{
            width: 1000,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-1000' }
            },
            {
            width: 800,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-800' }
            },
            {
            width: 400,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-400' },
        }]
        })
    )
    .pipe(dest('./img/'));
}

在上述示例中,原始图片 (monarch.png) 的大小超过 3.3MB。生成最大文件 此任务 (monarch-1000.jpeg) 大约为 150KB。最小的 monarch-400.web 只有 32KB。

[10:30:54] Starting 'default'...
[10:30:54] gulp-responsive: monarch.png -> monarch-400.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-800.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-400.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-800.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.webp
[10:30:54] gulp-responsive: Created 6 images (matched 1 of 1 image)
[10:30:54] Finished 'default' after 374 ms

当然,您需要仔细检查结果中是否有可见的压缩失真,或者可能提高压缩率 以进一步节省费用。由于此任务是非破坏性的,因此可以轻松更改这些设置。

总而言之,在经过精心的手动微优化后,您可以省出几千字节,从而获得一个 这款工具不仅效率高,而且弹性佳:一款工具可无缝运用您掌握的高性能图片素材资源知识 整个项目,无需任何人工干预。

自适应图片标记实际应用

填充 srcset 属性通常是一个简单的手动过程,因为属性实际上只捕获 与生成来源时已完成的配置相关的信息。在上述任务中,我们确定了 我们的属性将遵循的文件名和宽度信息:

srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w"

请注意,srcset 属性的内容是描述性的,不是规定性的。超载没有坏处 srcset 属性,只要每个来源的宽高比保持一致即可。srcset 属性可以包含 URI 服务器生成的每个备选剪切片段的宽度,而不会产生任何不必要的请求, 来源,浏览器就能越有效地定制请求。

正如您在自适应图片中所学到的,您需要利用 <picture> 元素来无缝处理 WebP 文件 或 JPEG 后备格式在这种情况下,您要将 type 属性与 srcset 搭配使用。

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

如您所知,支持 WebP 的浏览器会识别 type 属性的内容,并从中选择 <source> 元素的 srcset 属性作为候选图片的列表。浏览器未将“image/webp”识别为有效媒体 类型会忽略此 <source>,改为使用内部 <img> 元素的 srcset 属性。

在浏览器支持方面,还有一个因素:不支持任何自适应图片标记的浏览器 否则,我们就可能会出现图片损坏的风险,尤其是在旧版浏览环境中。由于 <picture><source>srcset 在这些浏览器中都会被忽略,我们需要在内部 <img>src 属性。

由于缩小图片在视觉上是无缝的,并且 JPEG 编码已被普遍支持,因此最大的 JPEG 是 合理的选择。

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img src="filename-1000.jpg" srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

处理 sizes 可能会有点难。正如您了解到的,sizes 必定与上下文相关 - 无法填充该属性,因为不知道图片将在渲染布局中占据的空间量。对于 尽可能高效地处理请求,但在提出此类请求时,我们的标记中必须包含准确的 sizes 属性 在请求控制页面布局的样式之前,由最终用户创建。完全省略 sizes 这不仅违反了 HTML 规范,还会导致相当于 sizes="100vw" 的默认行为,从而告知 浏览器,使该图片仅受视口本身的限制,从而产生最大的候选来源 所选对象。

与处理任何特别繁重的网络开发任务一样,我们已经开发了许多工具, 手写 sizes 属性的过程。respImageLint 绝对是 基本代码段,用于检查 sizes 属性的准确性并提供改进建议。 它以小书签的形式运行,小书签是浏览器中运行的一种工具,它指向包含图片的完整呈现网页 元素。在浏览器充分了解网页布局的环境中,浏览器还能实现近乎像素的完美 能够看出图片在任何可能的视口尺寸下在布局中应该占据的空间。

显示尺寸/宽度不匹配的自适应图片报告。

用于对 sizes 属性执行 lint 请求的工具当然很有用,但作为批发生成这些属性的工具具有更多价值。 如您所知,srcsetsizes 语法旨在以视觉上流畅的方式优化对图片素材资源的请求。虽然 不应在生产环境中使用,将默认的 sizes 占位值 100vw 设为完全合理的做法 同时在本地开发环境中处理页面布局。布局样式设置完毕后,运行 respImageLint 将为您提供量身定制的 sizes 属性,您可以将这些属性复制并粘贴到标记中,详细程度更高 而不是手写:

采用建议尺寸的自适应图片报告。

尽管由服务器渲染的标记发起的图片请求的发生速度过快,导致 JavaScript 无法生成客户端 sizes 属性, 如果这些请求是在客户端发起,则同一原因就不适用了。Lazysizes 项目 例如,您可以将图片请求完全延迟到布局创建完毕之后, sizes 的价值观 - 这可为您带来极大的便利,同时可以保证为您的用户提供最高效的请求。 不过请注意,这种方法确实意味着会牺牲服务器所渲染标记的可靠性和 浏览器都内置了多种优化功能,而且仅在网页呈现后再发起这些请求, 会对你的 LCP 得分产生负面影响

当然,如果您已经在使用 React 或 Vue 等客户端渲染框架,那就说明您已经负担了 在这些情况下,使用 Lazysizes 意味着您的 sizes 属性几乎可以被抽象化处理。 更好的一点是:由于对延迟加载的图片使用 sizes="auto" 可以获得共识, 因此,Lazysizes 实际上会成为 polyfill 来实现这些新标准化的浏览器行为。