彻底搞懂预加载属性 Preload 与 Prefetch

开发 前端
在性能优化中有一种手段叫做预加载,从字面意思理解就是提前加载页面所依赖的资源,在网络请求中,我们在使用到某些资源如:图片,JS,CSS等,在执行前总需要等待资源的下载,若我们能做到预先加载资源,则在资源执行的时候就不必等待网络的开销,从而可以达到加快渲染的效果。

在性能优化中有一种手段叫做预加载,从字面意思理解就是提前加载页面所依赖的资源,在网络请求中,我们在使用到某些资源如:图片,JS,CSS等,在执行前总需要等待资源的下载,若我们能做到预先加载资源,则在资源执行的时候就不必等待网络的开销,从而可以达到加快渲染的效果。而预加载常用的属性主要有两个:「preload」、「prefetch」。

preload 提前加载

Preload主要是让浏览器提前加载资源(加载后并不会立即执行),然后会在需要执行的时候执行。并且 onload 事件必须等页面所有资源都加载完成才触发,而当给某个资源加上 preload 后,该资源将不会阻塞 onload。


如何使用

  • 通过link标签创建

<!-- 使用 link 标签静态标记需要预加载的资源 -->
<link rel="preload" href="style.css" as="style">

<!-- 或使用脚本动态创建一个 link 标签 -->
<script>
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'style';
link.href = 'style.css';
document.head.appendChild(link);
</script>

  • 在HTTP响应头中加上preload字段

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

体验

比如页面同时加载了两个JS文件

<script src="./js/a.js"></script>
<script src="./js/b.js"></script>

正常来讲它们的加载顺讯应该与书写顺序一致。

我们给b.js配置预加载

<link rel="preload" as="script" href="./js/b.js" />

再来看一下它俩的加载顺序:

此时b.js已经在a.js之前进行加载了。

加载资源类型

preload 除了能够预加载脚本之外,还可以通过 as 指定别的资源类型,比如:

  • style 样式表
  • font:字体文件
  • image:图片文件
  • audio:音频文件
  • video:视频文件
  • document:文档

应用

「预加载字体」

preload比较常见的使用场景是用于字体文件的预加载,开发过程中处于对设计的高度还原,我们可能会使用自定义字体。但在使用过程中我们往往会遇到下面这种现象,页面首次加载时文字会出现短暂的字体样式闪动(FOUT,Flash of Unstyled Text),在网络情况较差时更加明显。主要原因是字体文件由css引入,在css解析后才会进行加载,加载完成之前浏览器只能使用降级字体。也就是说,字体文件加载的时机太迟,需要告诉浏览器提前进行加载,这恰恰是preload的用武之地。

图片

当我们为字体文件加上预加载后再来看看效果

<link rel="preload" as="font" crossorigin href="https://xxx/229c49c5.6rzn36.ttf">

再次刷新页面,我们可以看到页面没有出现文字样式闪动了,并且我们在network面板中可以看到字体文件的加载时机提前了,在浏览器请求html后很快就开始加载字体文件了。

图片

兼容性判断

const isPreloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;

if (!relList || !relList.supports) {
return false;
}

return relList.supports('preload');
};

prefetch 预判加载

preload 用于提前加载用于当前页面的资源,而 prefetch 则是用于加载未来(比如下一个页面)会用到的资源,并且告诉浏览器在空闲的时候去下载,它会将下载资源的优先级降到最低。

如何使用

  • 通过link标签创建

<!-- 使用 link 标签静态标记需要预加载的资源 -->
<link rel="prefetch" href="style.css" as="style">

<!-- 或使用脚本动态创建一个 link 标签 -->
<script>
const link = document.createElement('link');
link.rel = 'prefetch';
link.as = 'style';
link.href = 'style.css';
document.head.appendChild(link);
</script>

  • 在HTTP响应头中加上preload字段

Link: <https://xxx.com/static/styles.css>; rel=prefetch; as=style

体验

还是上面这个例子

<script src="./js/a.js"></script>
<script src="./js/b.js"></script>

正常来讲它们的加载顺讯应该与书写顺序一致。

图片

我们给a.js配置prefetch

<link rel="prefetch" as="script" href="./js/b.js" />

再来看一下它俩的加载顺序:

图片

此时我们会发现a.js的加载优先级已经降到最低了,当资源被下载完成后,会被存到浏览器缓存中,当从首页跳转到页面 A 的时候,假如页面 A 中引入了该脚本,那么浏览器会直接从 prefetch cache 中读取该资源,从而实现资源加载优化。

总结

  • preload  是告诉浏览器页面「必定」需要的资源,浏览器「一定会」加载这些资源
  • prefetch 是告诉浏览器页面「可能」需要的资源,浏览器「不一定会」加载这些资源
  • preload与prefetch都仅仅是加载资源,并不会执行
  • preload比prefetch优先级更高,prefetch比preload的兼容性更好
  • preload与prefetch都不会阻塞页面的onload
  • preload的字体资源必须设置crossorigin属性,否则会导致重复加载
责任编辑:华轩 来源: 前端南玖
相关推荐

2023-09-28 08:15:05

SpringBean加载

2022-02-25 14:19:56

依赖管理前端命令

2017-12-05 17:44:31

机器学习CNN卷积层

2020-10-14 08:50:38

搞懂 Netty 线程

2024-01-03 13:39:00

JS,Javascrip算法

2023-10-18 10:55:55

HashMap

2021-08-05 06:54:05

观察者订阅设计

2024-02-23 08:18:32

首屏产品浏览器

2023-05-29 08:12:38

2021-10-09 19:05:06

channelGo原理

2021-10-11 11:58:41

Channel原理recvq

2021-12-29 17:29:07

KubernetesEvents集群

2019-10-28 10:19:27

JVM 类加载器Java

2020-12-07 06:19:50

监控前端用户

2022-04-12 08:00:17

socket 编程网络编程网络 IO 模型

2021-07-08 10:08:03

DvaJS前端Dva

2021-06-30 08:45:02

内存管理面试

2022-06-07 10:13:22

前端沙箱对象

2022-04-24 11:06:54

SpringBootjar代码

2020-03-18 14:00:47

MySQL分区数据库
点赞
收藏

51CTO技术栈公众号