一.背景
在工作中的项目脚手架生成的H5页面中,其index.html 如下:
你发现了嘛。上面<link> 标签中写了一遍,下面<script> 标签中又写了一遍。
在<link> 中进行了 预加载, 在<script> 进行执行,执行时省略了下载步骤,节约了时间,即提前加载资源。
二.原理
<linkrel="preload"> 可以实现动态加载,但不执行,同时preload 不会阻塞 windows 的 onload 事件,除非,preload资源的请求刚好来自于会阻塞 window 加载的资源。
应用场景就是上述代码的那个场景:你想提前下载好某一个资源,但并不在下载结束后就执行下,等到某一时刻再执行。
在<linkrel="preload"> 出现之前,浏览器下载脚本之后会直接执行。
基于这个特点,如果你想在脚本插入的位置,直接执行脚本,而不等待其下载,那你就必须提前下载脚本。
现在开动脑筋想一下,提前获取某个网络资源有哪些方式?
首先想到的是发起请求,但是通过XHR获取的脚本,本质上是获取了当前脚本中的内容,而非说把这个脚本CV了一份到浏览器,因为浏览器不能写文件,所以这个内容我们只能先保存下来,后续只能通过eval() 方法执行,但eval() 本身也有副作用,导致其不是很可靠。
所以 preload 诞生了。
<linkrel=“prefetch”>的作用是告诉浏览器加载下一页面可能会用到的资源,注意,是下一页面,而不是当前页面。因此该方法的加载优先级非常低(自然,相比当前页面所需的资源,未来可能会用到的资源就没那么重要了),也就是说该方式的作用是加速下一个页面的加载速度。
三.preload解决了什么
HTML 解析器在创建 DOM 时如果碰上同步脚本(synchronous script),解析器会停止创建 DOM,转而去执行脚本。所以,如果资源的获取只发生在解析器创建 DOM时,同步脚本的介入将使网络处于空置状态,尤其是对外部脚本资源来说,当然,页面内的脚本有时也会导致延迟。
预加载器(Preloader)的出现就是为了优化这个过程,预加载器通过分析浏览器对 HTML 文档的早期解析结果(这一阶段叫做“令牌化(tokenization)”),找到可能包含资源的标签(tag),并将这些资源的 URL 收集起来。令牌化阶段的输出将会送到真正的 HTML 解析器手中,而收集起来的资源 URLs 会和资源类型一起被送到读取器(fetcher)手中,读取器会根据这些资源对页面加载速度的影响进行有次序地加载。
四.当前浏览器是否支持preload