dns-prefetch

DNS-prefetch (DNS 预获取) 是尝试在请求资源之前解析域名。提前解析域名。这可能是后面要加载的文件,也可能是用户尝试打开的链接目标。

使用注意点:

  • 仅对跨域的占点有效
  • [x] 最好与preconnect一起使用更有效,但要注意preconnect 的使用场景

    preconnect

    预连接。和DNS Prefetch类似,但是,更进一步。它不仅要求浏览器预解析指定域名的DNS,还需要预先与服务器握手以及TLS协商(如果使用了HTTPS)。提前进行tcp和tls

    使用注意点:

    如果页面需要建立与许多第三方域的连接,则将它们预先连接会适得其反。 preconnect 提示最好仅用于最关键的连接。对于其他的,只需使用 即可节省第一步的时间-DNS查找。

    1. <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
    2. <link rel="dns-prefetch" href="https://fonts.gstatic.com/">

    浏览器执行步骤:

  • 解释href的属性值,如果是合法的URL,然后继续判断URL的协议是否是http或者https否则就结束处理

  • 如果当前页面host不同于href属性中的host,crossorigin其实被设置为anonymous(就是不带cookie了),如果希望带上cookie等信息可以加上crossorign属性,corssorign就等同于设置为use-credentials

    prefetch

    同上面说的dns-prefetch
    允许浏览器在后台空闲时获取将来可能用到的资源,当执行到带有 prefetch的连接时,可以立刻从缓存中加载内容。link,dns,prerendering

    特点

  • [x] prefetch加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少5分钟(无论资源是否可以缓存)

  • [x] 当页面跳转时,未完成的prefetch请求不会被中断

    preload

  • [x] preload加载的资源是在浏览器渲染机制之前进行处理的,并且不会阻塞onload事件;

  • preload可以支持加载多种类型的资源,并且可以加载跨域资源
  • preload加载的js脚本其加载和执行的过程是分离的。即preload会预加载相应的脚本代码,待到需要时自行调用

    defer

    使用 async/defer 属性在加载脚本的时候不阻塞 HTML 的解析,defer 加载脚本执行会在所有元素解析完成,DOMContentLoaded 事件触发之前完成执行。它的用途其实跟 preload 十分相似。你可以使用 defer 加载脚本在 head 末尾,这比将脚本放在 body 底部效果来的更好。
  1. 它相比于 preload 加载的优势在于浏览器兼容性好,从 caniuse 上看基本上所有浏览器都支持,覆盖率达到 93%,
  2. 不足之处在于:defer 只作用于脚本文件,对于样式、图片等资源就无能为力了,并且 defer 加载的资源是要执行的,而 preload 只下载资源并不执行,待真正使用到才会执行文件。
  3. 对于页面上主/首屏脚本,可以直接使用 defer 加载,而对于非首屏脚本/其它资源,可以采用 preload/prefeth 来进行加载。

    defer和async的区别

    没有defer 和 async 时,浏览器会下载并执行js,阻塞dom解析
    async 时, 浏览器遇到 js 会异步解析和执行js,不会阻塞Dom解析
    defer时,DOM和js 异步加载,但是 js 的执行要在所有DOM解析完成之后,DOMContentLoaded 事件触发之前完成

    对比预加载 preload,prefetch,defer

    二次下载

    正确使用 preload/prefetch 不会造成二次下载,也就说:当页面上使用到这个资源时候 preload 资源还没下载完,这时候不会造成二次下载,会等待第一次下载并执行脚本
    preload 页面关闭,会立即停止 preload 获取资源
    prefetch页面关闭,prefetch 发起的请求仍会进行不会中断

    优先级

    prefetch 在浏览器那里优先级最低,闲时下载,如果浏览器比较忙就不下载了
    preload

  4. 可以通过 “as” 或者 “type” 属性来标识他们请求资源的优先级(比如说 preload 使用 as=”style” 属性将获得最高的优先级,即使资源不是样式文件)

  5. 没有 “as” 属性的将被看作异步请求。

    兼容性

    defer的覆盖率高达93%,prefetch 比 preload 的兼容性更好,覆盖面可以达到将近 80%。
    defer > prefetch > preload

    什么情况会导致二次获取?

  6. 不要将 preload 和 prefetch 进行混用,它们分别适用于不同的场景,对于同一个资源同时使用 preload 和 prefetch 会造成二次的下载。

  7. preload 字体不带 crossorigin 也将会二次获取! 确保你对 preload 的字体添加 crossorigin 属性,否则他会被下载两次,这个请求使用匿名的跨域模式。这个建议也适用于字体文件在相同域名下,也适用于其他域名的获取(比如说默认的异步获取)。

使用场景

  1. 提前加载字体文件。由于字体文件必须等到 CSSOM 构建完成并且作用到页面元素了才会开始加载,会导致页面字体样式闪动。所以要用 preload 显式告诉浏览器提前加载。假如字体文件在 CSS 生效之前下载完成,则可以完全消灭页面闪动效果。
  2. 使用 preload 预加载第二屏的内容,在网页开发中,对于非首屏部分采用懒加载是我们页面常用的优化手段,所以我们在页面 onload 之后可以通过 preload 来加载次屏所需要的资源,在用户浏览完首屏内容滚动时能够更快地看到次屏的内容。
  3. 在页面加载完成之后,可以分析页面上所有的链接,判断用户可能会点击的页面,分析提取下一跳页面上所有的资源使用 prefetch 进行加载(这里不使用 preload,因为不一定会点击),浏览器会在空闲地时候进行加载,当用户点击链接命中了缓存,这可以有效地提升下一页面的首屏渲染时间。
  4. 对于商品列表页面,在用户鼠标停留在某个商品的时候,可以去分析商品详情页所需要的资源并提前开启 preload 加载,跟第 3 点类似,都是用来预测用户的行为并且做出一些预加载的手段,区别在于当用户停留在商品上时,点击命中率更高,preload 可以立即加载资源,有效提升缓存命中率。

兼容性查看http://caniuse.com/#search=preconnect