标签: 预加载

  • 如何通过预加载 (Preload) 关键资源以提高网站加载速度

    如何通过预加载 (Preload) 关键资源以提高网站加载速度

    预加载允许您指定在页面加载期间立即或很快需要的资源(例如字体、图像、JavaScript 和 CSS)。 在您网站的每个页面的<head>…</head>部分顶部添加一个link rel='preload'标签。

    比如:

    <link rel=‘preload’ href=‘font.woff2’ as=‘font’ type=‘font/woff2’ crossorigin>
    <link rel=’preload’ href=’font.woff2′ as=’font’ type=’font/woff2′ crossorigin>
    <link rel='preload' href='font.woff2' as='font' type='font/woff2' crossorigin>

    打开网页时,浏览器会从服务器请求HTML文档,解析其内容,并为引用资源提交单独请求。作为开发人员,您知道页面需要的所有资源以及哪些资源最为重要。您可以使用这些知识提前请求关键资源,加快加载的过程。本文介绍了如何使用 <link> 来达成此目的。

    预加载的工作原理

    预加载最适合用于浏览器通常较晚发现的资源。

    预加载后期资源

    在本例中,Pacifico字体是在样式表通过 @font-face 规则定义的。浏览器只有在完成下载和解析样式表后才会加载字体文件。

    通过预加载某个资源,您希望浏览器可以比正常发现它更早地获取该资源,因为您认为它对当前页面很重要。

    预加载某个资源

    在本例中,已预加载了Pacifico字体,所以下载会与样式表并行进行。

    关键请求链代表着浏览器优先处理和获取的资源顺序。 Lighthouse会将位于该链第三层的资产识别为后期发现的资产。您可以使用预加载关键请求审计来确定要预加载的资源。

    预加载关键请求

    您可以通过在HTML文档的头部添加带有 rel="preload" 的 <link> 标记来预加载资源:

    <link as=“script” href=“critical.js”>
    <link as=”script” href=”critical.js”>
    <link as="script" href="critical.js">

    浏览器会缓存预加载的资源,以便在需要时立即可用。(它不会执行脚本或应用样式表。)

    在实施预加载后,包括Shopify、Financial Times和Treebo在内的许多网站在以用户为中心的指标(例如Time to InteractiveFirst Contentful Paint)等方面,都实现了1秒的改进。

    浏览器会根据情况执行诸如 preconnect 和 prefetch 等资源提示。而另一方面,preload 对浏览器来说是强制性的。现代浏览器已经非常擅长对资源进行优先级排序,这就是为什么谨慎使用 preload 并且只预加载最关键的资源那么重要。

    load 事件后大约3秒会触发Chrome中的控制台警告。

    谨慎使用 preload

    所有现代浏览器均支持 preload

    有助于修复以下两种类型的警告:

    1.预加载密钥请求

    预加载关键请求是Web字体的常见警告。Font Awesome是您可能会看到的一种非常常见的字体。

    预加载关键请求

    预加载关键请求

    2.渲染阻塞资源

    通过预加载,您还可以修复渲染阻塞资源警告,因为资产以非阻塞方式加载。

    消除渲染阻塞资源

    消除渲染阻塞资源

    如果您正在预加载图像,它还可以帮助降低最大内容绘制 (LCP) 时间。

    可预加载资源

    有许多不同的资源可以预加载。

    公共资源

    • font: 字体文件。
    • script: JavaScript文件。
    • style: CSS样式表。
    • image: 图像文件 ( .jpg.png.webp)。

    其他资源

    • audio: 音频文件
    • document: 旨在由 <frame><iframe>嵌入的HTML文档。
    • embed:要嵌入到 <embed> 元素中的资源。
    • fetch:要通过fetch或XHR请求访问的资源,例如ArrayBuffer或JSON文件。
    • object:要嵌入到 <object> 元素中的资源。
    • track: WebVTT文件。
    • worker:一个JavaScript网络worker或共享worker。
    • video: 视频文件。

    注意:在撰写本文时,Chrome存在一个未解决的bug,即预加载请求比其他更高优先级资源的获取速度更快。在解决此问题之前,请注意预加载的资源如何“跳过队列”并比应有的时间更早地被请求。

    预加载CSS中定义的资源

    在浏览器下载并解析CSS文件之前,不会发现这些文件中使用 @font-face 规则定义的字体或背景图像。预加载这些资源可确保在下载CSS文件之前获取它们。

    预加载CSS文件

    如果您使用了关键CSS方法,那么CSS将分成两部分。渲染首屏内容所需的关键CSS内联在文档的 <head> 中,非关键CSS通常使用JavaScript延迟加载。在加载非关键CSS之前等待JavaScript执行会导致用户滚动时呈现延迟,因此最好使用 <link> 更快地启动下载。

    预加载JavaScript文件

    由于浏览器不执行预加载的文件,因此预加载有助于将获取与执行分开,这可以改善Time to Interactive等指标。如果您拆分JavaScript包并仅预加载关键块,则预加载效果最佳。

    如何实现rel=preload

    实现 preload 最简单的方法是在文档的 <head> 中添加一个<link> 标记:

    <head> <link as=“script” href=“critical.js”></head>
    <head> <link as=”script” href=”critical.js”></head>
    <head>  <link as="script" href="critical.js"></head>

    提供 as 属性可帮助浏览器根据其类型来设置预获取资源的优先级,设置正确的标头,以及确定资源是否已存在于缓存中。此属性可接受的值包括: script 、style 、font 和 image 等等

    请查看Chrome Resource Priorities and Scheduling文档,详细了解浏览器如何确定不同类型资源的优先级。

    注意:省略 as 属性或使用了无效值,就相当于XHR请求,这时浏览器不知道它获取的内容,因此无法确定正确的优先级。它还可能导致某些资源(例如脚本)被获取两次。

    某些类型的资源,例如字体,以匿名模式加载。对于这些资源,您必须设置 preload 的 crossorigin 属性:

    <link href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>

    注意:没有设置 crossorigin 属性的预加载的字体将被获取两次!

    另外,<link> 元素还接受 type 属性,它包含链接资源的MIME类型。浏览器使用 type 属性的值来确保资源仅在其文件类型受支持时才被预加载。如果浏览器不支持指定的资源类型,它将忽略 <link> 。

    请尝试通过预加载web字体提高网页性能

    您可以通过 Link HTTP标头预加载任何类型的资源:

    Link: </css/style.css>;; as=“style”
    Link: </css/style.css>;; as=”style”
    Link: </css/style.css>;; as="style"

    在HTTP标头中指定 preload 的一个好处是,浏览器不需要解析文档来发现它,这在某些情况下可以提供一些小幅改进。

    使用webpack预加载JavaScript模块

    如果您使用了创建应用程序构建文件的模块打包器,则需要检查它是否支持预加载标签的注入。在webpack 4.6.0或更高版本中,它通过在 import()中使用magic comments(魔法注释)支持预加载:

    import(_/* webpackPreload: true */_ “CriticalChunk”)
    import(_/* webpackPreload: true */_ “CriticalChunk”)
    import(_/* webpackPreload: true */_ "CriticalChunk")

    如果您使用的是旧版webpack,请使用第三方插件,例如preload-webpack-plugin

    预加载时要记住的事项

    • 不要预加载每个脚本,否则它实际上会导致性能问题,例如增加总阻塞时间 (TBT)。预加载应该只用于立即需要的资源,因此它们以非阻塞方式加载。这通常用于网络字体、图像、CSS和JS。
    • 如果您正在使用缓存清除技术(例如查询字符串domain.com/style.css?ver=1.0),请不要忘记浏览器会看到确切的URL。因此,您将需要使用查询字符串URL,或者您可以使用句柄动态预加载。
    • 如果您有一个CDN重写您的资产的URL,请确保您要预加载的所有资源首先被正确地重写。如果URL不匹配,您最终可能会加载资源两次。
    • 如果您预加载样式表 (CSS) 或脚本 (JS),并且您正在使用插件来组合您的CSS/JSS(AutoptimizeWP Rocket等),请确保从连接过程中排除您预加载的资源。否则,它可能会被打包两次并最终在您的网站上放置更多代码。

    小结

    为提高网页速度,请预加载浏览器来发现较晚的重要资源。预加载全部资源会适得其反,因此请谨慎使用 preload,并衡量它在现实中的影响。

    via https://web.dev

  • 深入了解预加载关键图像技术

    深入了解预加载关键图像技术

    预加载主要图片(首屏图片)有助于减少Core Web Vitals中的最大内容绘制(LCP) 时间。这些通常是图像,如徽标、博客文章上的特色图像、登录页面上的Hero图像等。通过预加载它们,您将它们移动到瀑布的顶部,并基本上告诉浏览器这些具有优先级并且应该立即加载。

    最大的内容绘制时间

    最大的内容绘制时间

    重要的是要了解Chrome有两个图像预加载的限制,它们将出现在瀑布的最顶部。在这两个图像之后的任何内容仍然会在瀑布中显示得更高,但不会被视为高优先级,这完全取决于Chrome。我们通常建议预加载2-3个图像。这通常会预加载您的徽标并在博客文章中显示特色图片。

    如果您在页面上有手动图像预加载,这将优先于自动预加载之一。

    预加载关键图像功能还将自动从延迟加载中排除这些图像。

    从Chrome 73开始,链接 和响应式图像可以结合起来,以便更快地加载图像。

    预加载概述

    Preload让您可以在HTML中发现关键资源之前尽快告诉浏览器您想要加载的关键资源。这对于不容易发现的资源特别有用,例如样式表中包含的字体、背景图像或从脚本加载的资源。

    <link as=“image” href=“important.png”>
    <link as=”image” href=”important.png”>
    <link as="image" href="important.png">

    响应式图像 + 预加载 = 更快的图像加载

    响应式图像和预加载在过去几年中一直可用,但同时缺少一些东西:无法预加载响应式图像。从Chrome 73开始,浏览器可以在发现标签img之前预加载srcset指定的响应图像的正确变体!

    根据您网站的结构,这可能意味着图像显示速度显着加快!我们在一个使用JavaScript延迟加载响应式图像的网站上进行了测试。预加载导致图像加载速度提高了1.2秒。

    所有现代浏览器都支持响应式图像,而仅在基于Chromium的浏览器中支持预加载它们。

    imagesrcsetimagesizes

    为了预加载响应式图像,最近向<link>元素添加了新属性:imagesrcsetimagesizes. 它们与 <link rel="preload">一起使用,并与 <img>元素中使用的srcsetsizes语法相匹配。

    例如,如果您想预加载指定的响应式图像:

    <img src=“wolf.jpg” alt=“A rad wolf”>
    <img src=”wolf.jpg” alt=”A rad wolf”>
    <img src="wolf.jpg" alt="A rad wolf">

    您可以通过将以下内容添加到您的HTML的<head>来做到这一点:

    <link as=“image” href=“wolf.jpg” imagesrcset=“wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w” imagesizes=“50vw”>
    <link as=”image” href=”wolf.jpg” imagesrcset=”wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w” imagesizes=”50vw”>
    <link as="image" href="wolf.jpg" imagesrcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" imagesizes="50vw">

    这将使用srcsetsizes将应用的相同资源选择逻辑启动请求。

    用例

    预加载动态注入的响应图像

    假设您正在动态加载主图像作为幻灯片的一部分,并且知道将首先显示哪个图像。在这种情况下,您可能希望避免在加载相关图像之前等待脚本,因为这会延迟用户看到它的时间。

    您可以在具有动态加载的图片库的网站上检查此问题:

    1. 在新选项卡中打开此示例网站
    2. 按 `Control+Shift+J`(或 Mac 上的 `Command+Option+J`)打开DevTools。
    3. 单击网络选项卡。
    4. Throttling下拉列表中,选择Fast 3G
    5. 禁用禁用缓存复选框。
    6. 重新加载页面。

    Chrome开发者工具-network

    此瀑布显示图像仅在浏览器完成运行脚本后才开始加载,从而对最初向用户显示图像的时间引入了不必要的延迟。

    在此处使用preload帮助是因为图像会提前开始加载,并且在浏览器需要显示它时可能已经存在。

    使用reload预加载图像

    此瀑布显示第一张图片与脚本同时开始加载,避免了不必要的延迟并加快了图片的显示速度。

    要查看预加载的不同之处,您可以按照第一个示例中的步骤检查相同的动态加载的图像库,但预加载了第一张图像

    避免该问题的另一种方法是使用基于标记的轮播并让浏览器的预加载器获取所需的资源。然而,这种方法可能并不总是实用的。(例如,如果您正在重用现有的组件,它不是基于标记的。)

    使用图像集预加载背景图像

    如果对于不同的屏幕密度有不同的背景图像,则可以在CSS中使用image-set语法指定它们。然后浏览器可以根据屏幕的DPR选择显示哪一个。

    background-image: image-set( “cat.png” 1x, “cat-2x.png” 2x);
    background-image: image-set( “cat.png” 1x, “cat-2x.png” 2x);
    background-image: image-set( "cat.png" 1x, "cat-2x.png" 2x);

    上述语法忽略了在基于Chromium和WebKit的浏览器中此功能需要供应商前缀这一事实。如果您打算使用此功能,则应考虑使用Autoprefixer作为在线工具提供)来自动解决该问题。

    CSS背景图片的问题在于,它们只有在浏览器下载并处理了页面<head>中的所有CSS之后才会被浏览器发现,这可能是很多CSS……

    您可以在具有响应式背景图像的示例网站上检查此问题。

    响应式背景图像加载

    在此示例中,直到 CSS 完全下载后才开始图像下载,从而导致图像显示出现不必要的延迟。

    响应式图像预加载提供了一种简单且无需破解的方式来更快地加载这些图像。

    <link rel=preload href=cat.png as=image imagesrcset=“cat.png 1x, cat-2x.png 2x”>
    <link rel=preload href=cat.png as=image imagesrcset=”cat.png 1x, cat-2x.png 2x”>
    <link rel=preload href=cat.png as=image imagesrcset="cat.png 1x, cat-2x.png 2x">

    您可以检查前面的示例如何处理预加载的响应式背景图像

    预加载的响应式背景图像

    在这里,图像和CSS同时开始下载,避免了延迟,从而加快了图像的加载速度。

    预加载响应式图像

    理论上,预加载响应式图像可以加快速度,但实际上它有什么作用呢?

    为了回答这个问题,我们来看看创建了一个演示PWA商店的两个副本:一个不预加载图像另一个预加载其中的一些。由于该站点使用JavaScript延迟加载图像,因此可能会从预加载将在初始视口中的图像受益。

    这给了我以下关于no preloadimage preload的结果。查看原始数据,我们看到Start Render保持不变,速度指数略有提高(273 毫秒,因为图像到达速度更快,但不占用大量像素区域),但捕捉差异的真实指标是最后绘制的Hero指标,提高了1.2 秒。

    当然,没有什么比幻灯片比较更能捕捉视觉差异了:

    预加载与无预加载页面渲染对比

    幻灯片显示,图像在预加载时的到达速度明显更快,从而极大地改善了用户体验。

    预加载和<picture>

    如果您熟悉响应式图像,您可能想知道“怎么<picture>办?”。

    Web性能工作组正在讨论为srcsetand添加一个等效的预加载sizes,但不是为处理 “art direction” 用例的<picture>元素。

    为什么这个用例被“忽视”?

    尽管也有兴趣解决该用例,但仍有许多技术问题需要解决,这意味着这里的解决方案将具有很大的复杂性。最重要的是,在大多数情况下,用例似乎可以在今天得到解决,即使是以一种hacky的方式(见下文)。

    鉴于此,Web Performance WG决定srcset先发布,看看是否需要同等picture支持。

    如果您确实发现自己可以预加载<picture>,则可以使用以下技术作为解决方法。

    鉴于以下情况:

    <picture>
    <source srcset=“small_cat.jpg” media=“(max-width: 400px)”>
    <source srcset=“medium_cat.jpg” media=“(max-width: 800px)”>
    <img src=“large_cat.jpg”>
    </picture>
    <picture>
    <source srcset=”small_cat.jpg” media=”(max-width: 400px)”>
    <source srcset=”medium_cat.jpg” media=”(max-width: 800px)”>
    <img src=”large_cat.jpg”>
    </picture>
    <picture>
        <source srcset="small_cat.jpg" media="(max-width: 400px)">
        <source srcset="medium_cat.jpg" media="(max-width: 800px)">
        <img src="large_cat.jpg">
    </picture>

    <picture>元素的逻辑(或者确切地说是图像源选择逻辑)是按顺序检查<source>元素的media属性,找到第一个匹配的,然后使用附加的资源。

    因为响应式预加载没有“顺序”或“第一次匹配”的概念,所以需要将断点转换为以下内容:

    <link rel=“preload” href=“small_cat.jpg” as=“image” media=“(max-width: 400px)”>
    <link rel=“preload” href=“medium_cat.jpg” as=“image” media=“(min-width: 400.1px) and (max-width: 800px)”>
    <link rel=“preload” href=“large_cat.jpg” as=“image” media=“(min-width: 800.1px)”>
    <link rel=”preload” href=”small_cat.jpg” as=”image” media=”(max-width: 400px)”>
    <link rel=”preload” href=”medium_cat.jpg” as=”image” media=”(min-width: 400.1px) and (max-width: 800px)”>
    <link rel=”preload” href=”large_cat.jpg” as=”image” media=”(min-width: 800.1px)”>
    <link rel="preload" href="small_cat.jpg" as="image" media="(max-width: 400px)">
    <link rel="preload" href="medium_cat.jpg" as="image" media="(min-width: 400.1px) and (max-width: 800px)">
    <link rel="preload" href="large_cat.jpg" as="image" media="(min-width: 800.1px)">

    小结

    响应式图像预加载为我们提供了新的和令人兴奋的可能性,以以前只能使用hack的方式预加载响应式图像。它是对速度敏感的开发人员工具箱的重要新增功能,使我们能够确保我们希望尽快呈现在用户面前的重要图像在我们需要时会出现。