一年多前,Chrome Aurora 团队发布了 Angular NgOptimizedImage 指令。该指令主要侧重于提高性能(根据核心网页指标指标进行衡量)。它将常见的图片优化和最佳做法捆绑在一个面向用户的 API 中,该 API 并不比标准 <img>
元素复杂得多。
2023 年,我们通过新功能增强了指令。这篇博文介绍了这些新功能中最重要的功能,并强调了我们选择优先考虑每项功能的原因,以及这些功能如何帮助提升 Angular 应用的性能。
新功能
随着时间推移,NgOptimizedImage 得到了显著改进,其中包括以下新功能。
填充模式
通过提供 width
和 height
属性调整图片大小是减少布局偏移的一项极为重要的优化,因为浏览器需要知道图片的宽高比才能为图片节省空间。但是,调整图片大小对应用开发者来说是一项额外的工作,对于某些图片用例来说没有意义。
为帮助解决这一问题,我们在图片组件后开发者预览版中添加的首个主要功能是:填充模式。通过这种方式,开发者可以添加图像,而无需明确调整图像大小,并且不会导致布局偏移。
使用填充模式时,系统会停用图片大小要求,并自动调整图片样式以填充所含元素。这样可以将图片的宽高比与其在网页上所占空间分离开来,并可让您更好地控制图片与页面布局的契合方式。
填充模式使用 NgOptimizedImage 作为 background-image
css 属性的效果更好的替代方案。将图片放在 <div>
或具有 background-image
样式的其他元素内,然后启用填充模式,如上述代码示例所示。使用 <div>
上的 object-fit
和 object-position
CSS 属性来控制图片在后台的放置方式。
// Height and width are required
<img ngSrc="example.com" height="300" width="400">
// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
<img ngSrc="example.com" fill>
</div>
Srcset 生成
最有效的图片优化技术之一是使用 srcset
属性来确保为访问您应用的设备下载适当大小的图片。在整个应用中使用 srcset
不仅可以避免浪费带宽,还可以显著提高 LCP Core Web Vitals。
srcset
属性的缺点是实现起来可能很麻烦。手动写出 srcset
值意味着向应用中的每个图片元素添加多行标记,并为每个 srcset
添加多个自定义网址。您还必须确定一组断点,这很复杂,因为它们可以同时表示屏幕密度和常见设备的视口尺寸。
因此,将自动 srcset 生成添加到 NgOptimizedImage 指令是发布后的一个主要里程碑。添加之后,任何使用支持图片大小调整的 CDN 的应用都可以获得完整的、可自定义的 srcset,自动添加到使用 NgOptimizedImage 指令生成的每张图片。
我们添加了用于设置 sizes
属性的简化 API,该 API 用于确保每张图片都能获得正确类型的 srcset
。如果您未添加 sizes
属性,我们知道该图片将是固定尺寸,并且应获取与密度相关的 srcset,如下所示:
<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >
这种 srcset 可确保在提供图片的尺寸时考虑到用户的设备像素密度。
另一方面,如果您添加了 sizes
属性,NgOptimizedImage
会使用以下默认的断点列表生成一个自适应 srcset,其中包含适用于许多常见设备和图片尺寸的断点:
[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]
连接前生成
为了改进 LCP,请务必减少用户下载 LCP 映像所用的时间。在上一部分中,您了解了 srcset
如何帮助传输较小的图片文件,但同样重要的优化措施是尽快开始传输。为实现此目的,一种方法是使用 link rel="preconnect"
标记启动与图片网域的连接。
如果您未能预先连接到 LCP 映像的网域,NgOptimizedImage 从一开始就会发出警告,但警告并不是理想的解决方案,我们只是想为您解决问题。这正是 NgOptimizedImage,它现在通过自动生成预连接来实现这一点。
为了支持此功能,我们会使用静态代码分析来尝试在 NgOptimizedImage 加载器中检测图片网域,并为这些网域自动生成预连接链接标记。在某些情况下,仍然可能需要进行手动预连接链接,但对于大多数用户而言,自动预连接意味着只需少一步,就能获得良好的图片效果。
增强了对自定义加载器的支持
NgOptimizedImage 的关键元素是加载器架构,该架构可让指令自动生成适用于应用的图片 CDN 的网址。我们为广泛使用的 CDN 添加了一组内置加载器。我们还提供了自定义加载器,让您能够将 NgOptimizedImage 与几乎任何图片托管解决方案集成在一起。
在启动时,这些自定义加载器的范围有限,只能从图片元素中读取 width
属性。为响应用户反馈,我们添加了对可自定义 loaderParams
数据结构的支持,以允许将任意数据从图片元素传递到自定义加载器。随着扩展,自定义加载器可以按照应用图像基础架构的要求简单或复杂。
以下示例展示了简单的自定义加载器如何使用 loaderParams
API 在两个替代映像网域之间进行选择:
const myCustomLoader = (config: ImageLoaderConfig) => {
if (config.loaderParams?.alternateDomain) {
return `https://alternate.domain.com/images/${config.src}`
}
return `https://primary.domain.com/images/${config.src}`;
};
Angular 文档中提供了一个更复杂的自定义加载器的示例。
扩展了图片性能指南
到目前为止,我们添加到 Angular 的每个图片性能提醒都是 NgOptimizedImage 指令的一部分。如果您不在应用中使用该指令,则无法获得任何有关图片性能问题的指导。
在 Angular 17 中,我们将扩展图片性能指南的范围,以涵盖所有 Angular 应用。现在,如果我们检测到已知会造成性能影响错误的图片模式,例如延迟加载 LCP 图片或下载对网页来说过大的文件,我们也会通知您,即使您未使用 NgOptimizedImage。
图像性能对所有应用都至关重要,我们很高兴继续为之保驾护航,帮助预防 Angular 应用中的常见错误。
展望未来
我们已经在努力为 NgOptimizedImage 开发下一组功能。虽然图像性能仍然是我们关注的重点,但我们还希望添加一些功能来改善开发者体验,以确保 NgOptimizedImage 仍然是吸引在 Angular 应用中添加图像的选择。
我们应该优先考虑的一项功能是图片占位符。这些参数通常用于让图片加载在 Web 应用中看起来更美观,但如果实现不当,可能会降低性能。我们希望在 NgOptimizedImage 中构建性能优先的映像占位符系统。敬请关注我们的博客,及时了解最新公告!