使用preload预加载页面资源时注意事项

preload 提供了一种声明式的命令,让浏览器提前加载指定资源(加载后并不执行),在需要执行的时候再执行。提供的好处主要是

将加载和执行分离开,可不阻塞渲染和 document 的 onload 事件

提前加载指定资源,不再出现依赖的 font 字体隔了一段时间才刷出

如何使用 preload 使用 link 标签创建

<!-- 使用 link 标签静态标记需要预加载的资源 --> <link href="https://www.jb51.net/path/to/style.css" as="style"> <!-- 或使用脚本动态创建一个 link 标签后插入到 head 头部 --> <script> const link = document.createElement('link'); link.rel = 'preload'; link.as = 'style'; link.href = 'https://www.jb51.net/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 进行预加载,如:

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

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

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

使用preload预加载页面资源时注意事项

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

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

如何区分 preload 和 prefetch

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

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

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

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

preload 将提升资源加载的优先级

使用 preload 前,在遇到资源依赖时进行加载:

使用preload预加载页面资源时注意事项

使用 preload 后,不管资源是否使用都将提前加载:

使用preload预加载页面资源时注意事项

可以看到,preload 的资源加载顺序将被提前:

使用preload预加载页面资源时注意事项

避免滥用 preload

使用 preload 后,Chrome 会有一个警告:

使用preload预加载页面资源时注意事项

如上文所言,若不确定资源是必定会加载的,则不要错误使用 preload,以免本末倒置,给页面带来更沉重的负担。

当然,可以在 PC 中使用 preload 来刷新资源的缓存,但在移动端则需要特别慎重,因为可能会浪费用户的带宽。

避免混用 preload 和 prefetch

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

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

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

使用preload预加载页面资源时注意事项

避免错用 preload 加载跨域资源

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

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

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

然而我发现这个文件加载了两次:

使用preload预加载页面资源时注意事项

使用preload预加载页面资源时注意事项

使用preload预加载页面资源时注意事项

原因是对跨域的文件进行 preload 的时候,我们必须加上 crossorigin 属性:

<link as="font" crossorigin href="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.

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

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

我们先来看一张图:

使用preload预加载页面资源时注意事项

这张表详见:Chrome Resource Priorities and Scheduling

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/c7fc92e8f5457cace838d68171811bac.html