preload、prefetch的认识

预加载

如今的网络状况虽然很乐观,可是css

defer和async

当浏览器碰到 script 脚本的时候:html

<script src="script.js"></script>segmentfault

没有 defer 或 async,浏览器会当即加载并执行指定的脚本,“当即”指的是在渲染该 script 标签之下的文档元素以前,也就是说不等待后续载入的文档元素,读到就加载并执行。浏览器

<script async src="script.js"></script>网络

有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。app

<script defer src="myscript.js"></script>异步

有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),可是 script.js 的执行要在全部元素解析完成以后,DOMContentLoaded 事件触发以前完成。async

而后从实用角度来讲呢,首先把全部脚本都丢到 </body> 以前是最佳实践,由于对于旧浏览器来讲这是惟一的优化选择,此法可保证非脚本的其余一切元素可以以最快的速度获得加载和解析。性能

接着,咱们来看一张图咯:fetch

clipboard.png

此图告诉咱们如下几个要点:

  1. defer 和 async 在网络读取(下载)这块儿是同样的,都是异步的(相较于 HTML 解析)
  2. 它俩的差异在于脚本下载完以后什么时候执行,显然 defer 是最接近咱们对于应用脚本加载和执行的要求的
  3. 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
  4. async 则是一个乱序执行的主,反正对它来讲脚本的加载和执行是牢牢挨着的,因此无论你声明的顺序如何,只要它加载完了就会马上执行
  5. 仔细想一想,async 对于应用脚本的用处不大,由于它彻底不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些能够不依赖任何脚本或不被任何脚本依赖的脚原本说倒是很是合适的,

preload和refetch

preload一般在页面中,咱们须要加载一些脚本和样式,而使用 preload 能够对当前页面所需的脚本、样式等资源进行预加载,而无需等到解析到 script 和 link 标签时才进行加载。这一机制使得资源能够更早的获得加载并可用,且更不易阻塞页面的初步渲染,进而提高性能。

使用方式
将 link 标签的 rel 属性的值设为 preload,as 属性的值为资源类型(如脚本为 script,样式表为 style)

<head>
  <meta charset="utf-8">
  <title>preload example</title>
  <!-- 对 style.css 和 index.js 进行预加载 -->
  <link rel="preload" href="style.css" as="style">
  <link rel="preload" href="index.js" as="script">

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div id="app"></div>

  <script src="index.js"></script>
</body>

prefetchpreload 同样,都是对资源进行预加载,可是 prefetch 加载的资源通常不是用于当前页面的,即将来极可能用到的这样一些资源,简单点说就是其余页面会用到的资源。固然,prefetch 不会像 preload 同样,在页面渲染的时候加载资源,而是利用浏览器空闲时间来下载。当进入下一页面,就可直接从 disk cache 里面取,既不影响当前页面的渲染,又提升了其余页面加载渲染的速度。

使用方式
preload 很类似,无需指定 as 属性:

<head>
  <meta charset="utf-8">
  <title>preload example</title>
  <!-- 对 style.css 和 index.js 进行 preload 预加载 -->
  <link rel="preload" href="style.css" as="style">
  <link rel="preload" href="index.js" as="script">

  <!-- 对资源进行 prefetch 预加载 -->
  <link rel="prefetch" href="next.css">
  <link rel="prefetch" href="next.js">

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div id="app"></div>

  <script src="index.js"></script>
</body>

总结:对当前页面须要的资源,使用 preload 进行预加载,对其它页面须要的资源进行 prefetch 预加载。

Subresource和Prerender

subresource能够用来指定资源是最高优先级的。好比,在Chrome和Opera中咱们能够加上下面的代码:

<link rel="subresource" href="styles.css">

Chromium的文档这么解释:
和 "Link rel=prefetch"的语义不一样,"Link rel=subresource"是一种新的链接关系。rel=prefetch指定了下载后续页面用到资源的低优先级,而rel=subresource则是指定当前页面资源的提早加载。

因此,若是资源是在当前页面须要,或者立刻就会用到,则推荐用subresource,不然仍是用prefetch。

prerender是一个重量级的选项,它可让浏览器提早加载指定页面的全部资源。

<link rel="prerender" href="/thenextpage.html" />

Steve Souders的文章详细解释了这个技术:
prerender就像是在后台打开了一个隐藏的tab,会下载全部的资源、建立DOM、渲染页面、执行JS等等。若是用户进入指定的连接,隐藏的这个页面就会进入立刻进入用户的视线。Google Search多年前就利用了这个特性实现了Instant Pages功能。微软最近也宣布会让Bing在IE11上用相似prerender的技术。

可是要注意,必定要在十分肯定用户回点某个连接时才用这个特性,不然客户端就会无故的下载不少资源和渲染这个页面。
正如任何提早的动做同样,预判老是有必定风险出错。若是提早的动做是昂贵的(好比高CPU、耗电、占用带宽),就要谨慎使用了。虽然不容易预判用户会点进哪一个页面,但仍是存在一些典型的场景:

若是用户搜索到了一个明显正确的结果时,那么这个页面就颇有可能被点入
若是用户在登陆页面,那么登陆成功后的页面就极可能接下来会被加载了
若是用户在阅读一个多页面的文章或者有页码的内容时,下一页就极可能会立刻被点击了
利用Page Visibility API能够用来防止页面在还没真正展现给用户时就触发了JS的执行。

参考:
defer和async
prefetch与 preload
prefetch预加载
preload立即加载
加载技术概述
dnc fetch

Prerender Subresource

相关文章
相关标签/搜索