页面性能优化:preload预加载静态资源

本文主要介绍preload的使用,以及与prefetch的区别。然后会聊聊浏览器的加载优先级。

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

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

如何使用 preload

使用 link 标签创建

<!-- 使用 link 标签静态标记需要预加载的资源 --><link rel="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 进行预加载,如:

<link rel="preload" as="font" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff"><link rel="preload" as="script" href="https://a.xxx.com/xxx/PcCommon.js"><link rel="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) { 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 后,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:

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

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

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

<link rel="preload" 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.

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

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

我们先来看一张图:

这张表详见:Chrome Resource Priorities and Scheduling

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

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

html 主要资源,其优先级是最高的

css 样式资源,其优先级也是最高的

CSS(match) 指的是对已有的 DOM 具备规则的有效的样式文件。

script 脚本资源,优先级不一

前三个 js 文件是写死在 html 中的静态资源依赖,后三个 js 文件是根据首屏按需异步加载的组件资源依赖,这正验证了这个规则。font 字体资源,优先级不一

css 样式文件中有一个 @font-face 依赖一个 font 文件,样式文件中依赖的字体文件加载的优先级是 Highest; 在使用 preload 预加载这个 font 文件时,若不指定 crossorigin 属性(即使同源),则会采用匿名模式的 CORS 去加载,优先级是 High,看下图对比: 第一条 High 优先级也就是 preload 的请求:

第二条 Highest 也就是样式引入的请求:

可以看到,在 preload 的请求中,缺少了一个 origin 的请求头字段,表示这个请求是匿名的请求。 让这两个请求能共用缓存的话,目前的解法是给 preload 加上 crossorigin 属性,这样请求头会带上 origin, 且与样式引入的请求同源,从而做到命中缓存:

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

这么请求就只剩一个:

在网络瀑布流图中,也显示成功预加载且后续命中缓存不再二次加载:

总结

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

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

原文地址:https://www.cnblogs.com/cangqinglang/p/11308243.html

时间: 2024-10-16 05:06:33

页面性能优化:preload预加载静态资源的相关文章

mkinitrd --preload预加载raid模块

mkinitrd可建立映像文件,以供Linux开机时载入ramdisk 如何应用 -f 若指定的映像问家名称与现有文件重复,则覆盖现有的文件. -v 执行时显示详细的信息. --omit-scsi-modules 不要载入SCSI模块. --preload=<模块名称> 指定要载入的模块. --with=<模块名称> 指定要载入的模块. --version 显示版本信息. 目前遇到的瓶颈是如何正确的将raid驱动模块加载到内存中,当linux开机的过程中识别到 硬盘正确的挂载. m

如何让aspnet服务加载静态资源html(我的动态网页静态化) 转

我们知道,IIS自身是不能处理像ASPX扩展名这样的页面,只能直接请求像HTML这样的静态文件. 当客户端请求一个服务器资源时,这个HTTP请求会被inetinfo.exe进程截获(www服务),然后Check请求资源的类型,并依据资源映射信息(存储在IIS元库中,一种IIS专用的配置数据库)将请求的资源分配给特定的处理程序模块.1,如果是静态资源的请求,则分配由IIS处理(IIS在本地Web Server上访问请求的文件),将内容输出到控制台,发出请求的浏览器就能接收到它了.-----End2

Flask之加载静态资源

Flask之加载静态资源 1.加载css样式 <link rel="stylesheet" href="{{ url_for('static',filename='css/img.css',_external=True) }}"> 2.加载js脚本 <script rel="stylesheet" src="{{ url_for('static',filename='js/img.js') }}">&l

spring mvc 加载静态资源

由于我们在web.xml进行了如下配置: <servlet> <servlet-name>spring_mvc_demo</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> &l

Spring mvc应用 加载静态资源的几种方式

总结几种Spring mvc应用加载静态资源的方式 1.使用服务器的默认Servlet处理 对于不同的服务器,处理静态资源的servlet-name不一样,需要去看服务器具体的配置文件 比如resin-3.1.12,通过查看app-default.xml可以看到默认处理jsp的servlet-name为>resin-jsp 所以可以通过在web.xml中添加静态资源的访问 <servlet-mapping>        <servlet-name>resin-jsp<

laravel框架加载静态资源注意事项

laravel框架加载静态资源 要注意路径问题,一般静态资源都保存在public目录下 默认访问的路径就指向public目录,用 / 表示public目录 静态资源加载示例: <link href="/admin/css/bksystem.css" rel="stylesheet" type="text/css" /> bksystem.css文件存放在public目录下的admin目录下的css文件下面,这里最前面的/千万不要省略否

移动网站性能优化:网页加载技术概览

性能一直是网站成功的关键.越来越多的研究已经证明,不管是小型电商,还是像沃尔玛那样的连锁店,即使是页面加载时间方面的细微改善,都可以带来更多的业务,更多的广告收入,更多的用户粘性和更多的客户满意度. 在过去几年,Web开发者都是基于改善硬件或者提高带宽速度来优化用户体验.但是最近几年,爆炸式的移动Web浏览器的使用打破了这个途径.低带宽,高延迟,小内存,低处理器性能的移动设备环境,迫使开发者不得不想办法通过优化前端页面的性能来满足用户的性能预期. 在强调如何解决移动端性能问题上,这篇文章总结了一

移动网站性能优化:网页加载(转)

原文链接:http://caibaojian.com/mobile-optimization.html 由于移动设备存在的环境限制,如低带宽,高延迟,小内存,低处理器性能的等,迫使开发者不得不想办法通过优化前端页面的性能来满足用户的性能预期.在强调如何解决移动端性能问题上,这篇文章总结了一些前端优化的案例,并且概括了一些加速页面的方法和策略.· 为什么性能会影响这么多 不论你的页面设计地多么有趣.漂亮.交互性好,不管是在桌面还是移动设备上,如果页面需要花2到3秒时间去渲染展示,那么用户都会很快变

刚入前端整合的一个手机端页面适配+预加载+获取资源加载进度等的一个小模板

刚入前端不久,之前主要学的是pc端的布局,到公司之后负责的主要是移动段页面,刚开始时为了使页面适应移动端不同的屏幕大小采用的是百分比加媒体查询的方式,做完一个项目之后,感觉非常不好,虽然最后也基本使页面做到了适配.所以做完这个项目之后,我就在网上查找各种屏幕适配的方案,最终找到了一个通过js控制使页面整体缩放的方案,还有一个就是通过js实时检测屏幕大改变html根字体大小的rem布局方案.目前我在使用的是缩放的方案.整体代码基本上是整合的是大牛们分享的一些实用代码,如有什么bug欢迎提出,共同进