用 preload 预加载页面资源

发布于 2022-11-06 16:45:58 字数 5281 浏览 141 评论 0

本文主要介绍 preload 的使用,以及与 prefetch 的区别。然后会聊聊浏览器的加载优先级。preload 提供了一种声明式的命令,让浏览器提前加载指定资源(加载后并不执行),在需要执行的时候再执行。提供的好处主要是

  • 将加载和执行分离开,可不阻塞渲染和 document 的 onload 事件
  • 提前加载指定资源,不再出现依赖的 font 字体隔了一段时间才刷出

如何使用 preload

使用 link 标签创建

<!-- 使用 link 标签静态标记需要预加载的资源 -->
<linkrel="preload"href="/path/to/style.css"as="style">
<!-- 或使用脚本动态创建一个 link 标签后插入到 head 头部 -->
<script>
const link = document.createElement('link'); link.rel = 'preload'; link.as = 'style'; link.href = '/path/to/style.css'; document.head.appendChild(link); </script>

使用 HTTP 响应头的 Link 字段创建

Link: <https://example.com/other/styles.css>; rel=preload; as=style

如我们常用到的 antd 会依赖一个 CDN 上的 font.js 字体文件,我们可以设置为提前加载,以及有一些模块虽然是按需异步加载,但在某些场景下知道其必定会加载的,则可以设置 preload 进行预加载,如:

<linkrel="preload"as="font"href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">
<linkrel="preload"as="script"href="https://a.xxx.com/xxx/PcCommon.js">
<linkrel="preload"as="script"href="https://a.xxx.com/xxx/TabsPc.js">

如何判断浏览器是否支持 preload

目前我们支持的浏览器主要为高版本 Chrome,所以可放心使用 preload 技术。其他环境在 caniuse.com 上查到的支持情况如下:

在不支持 preload 的浏览器环境中,会忽略对应的 link 标签,而若需要做特征检测的话,则:

const isPreloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;
if (!relList || !relList.supports) { returnfalse; } return relList.supports('preload'); };

如何区分 preload 和 prefetch

  • preload 是告诉浏览器页面必定需要的资源,浏览器一定会加载这些资源;
  • prefetch 是告诉浏览器页面可能需要的资源,浏览器不一定会加载这些资源。

preload 是确认会加载指定资源,如在我们的场景中,x-report.js 初始化后一定会加载 PcCommon.js 和 TabsPc.js,则可以预先 preload 这些资源;

prefetch 是预测会加载指定资源,如在我们的场景中,我们在页面加载后会初始化首屏组件,当用户滚动页面时,会拉取第二屏的组件,若能预测用户行为,则可以 prefetch 下一屏的组件。

避免滥用 preload

使用 preload 后,Chrome 会有一个警告,如上文所言,若不确定资源是必定会加载的,则不要错误使用 preload,以免本末导致,给页面带来更沉重的负担。当然,可以在 PC 中使用 preload 来刷新资源的缓存,但在移动端则需要特别慎重,因为可能会浪费用户的带宽。

避免混用 preload 和 prefetch

preload 和 prefetch 混用的话,并不会复用资源,而是会重复加载。

<link rel="preload" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">
<link rel="prefetch" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">

使用 preload 和 prefetch 的逻辑可能不是写到一起,但一旦发生对用一资源 preload 或 prefetch 的话,会带来双倍的网络请求,这点通过 Chrome 控制台的网络面板就能甄别。

避免错用 preload 加载跨域资源

若 css 中有应用于已渲染到 DOM 树的元素的选择器,且设置了 @font-face 规则时,会触发字体文件的加载。
而字体文件加载中时,DOM 中的这些元素,是处于不可见的状态。对已知必加载的 font 文件进行预加载,除了有性能提升外,更有体验优化的效果。

在我们的场景中,已知 antd.css 会依赖 font 文件,所以我们可以对这个字体文件进行 preload:

<linkrel="preload"as="font"href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">

然而我发现这个文件加载了两次,原因是对跨域的文件进行 preload 的时候,我们必须加上 crossorigin 属性:

<linkrel="preload"as="font"crossoriginhref="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">

再看一下网络请求,就变成一条了。

W3 规范是这么解释的:Preload links for CORS enabled resources, such as fonts or images with a crossorigin attribute, must also include a crossorigin attribute, in order for the resource to be properly used.

那为何会有两条请求,且优先级不一致,又没有命中缓存呢?这就得引出下一个话题来解释了。

不同资源加载的优先级规则

在 Chrome 46 以后的版本中,不同的资源在浏览器渲染的不同阶段进行加载的优先级。在这里,我们只需要关注 DevTools Priority 体现的优先级,一共分成五个级别:

  • Highest 最高
  • Hight 高
  • Medium 中等
  • Low 低
  • Lowest 最低

总结

preload 是个好东西,能告诉浏览器提前加载当前页面必须的资源,将加载与解析执行分离开,做得好可以对首次渲染带来不小的提升,但要避免滥用,区分其与 prefetch 的关系,且需要知道 preload 不同资源时的网络优先级差异。

preload 加载页面必需的资源如 CDN 上的字体文件,与 prefetch 预测加载下一屏数据,兴许是个不错的组合。

参考资料

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

相思故

暂无简介

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文