dns-prefetch、preconnect、prefetch和preload

449 阅读4分钟

dns-prefetch 和 preconnect

使用dns-prefetch和preconnect可以提高页面资源加载效率,其具体表现为:

  • dns-prefetch: 告知浏览器对指定域名进行DNS解析。当后续请求该域名资源时可省掉DNS解析的时间。
  • preconnect: 告知浏览器与指定域名的服务器建立连接。当后续请求该域名资源时,可直接使用已建立好的连接,省掉了 DNS+TCP+TLS 的时间。

使用工具 chrome、wireshark

使用chrome访问页面前,要先将devTool打开,并在network面板中选中 "Disable cache" 选项,禁用浏览器缓存。

测试数据: 通过在页面中延迟插入一个加载js资源的<script>元素来统计资源加载时长,测试数据为:

仅加载:128ms/97ms/98ms/90ms/105ms 平均值103.6ms

仅dns-prefetch:53ms/45ms/41ms/42ms/44ms 平均值45ms

dns-prefetch + preconnect:28ms/12ms/21ms/12ms/18ms 平均值18.2ms

仅preconnect:14ms/14ms/20ms/13ms/22ms 平均值16.6ms

可见dns-prefetch确实可省掉DNS解析的时间,而preconnect在dns-prefetch的基础上又省掉了TCP和TLS握手的时间,确实有效。

prefetch 和 preload

preload和prefetch的出现为我们提供了可以更加细粒度地控制浏览器加载资源的方法。

preload

link标签的preload是一种声明式的资源获取请求方式,用于提前加载一些需要的依赖,并且不会影响页面的onload事件,使用方式如下:

<link rel="preload" as="script" href="test.js" onload="handleOnload()" onerror="handlepreloadError()">
<link rel="preload" as="style" href="test.css" onload="this.rel=stylesheet"> // css加载后立即生效
  • 其中,rel属性值为preload;
  • as属性用于规定资源的类型,并根据资源类型设置Accep请求头,以便能够使用正常的策略去请求对应的资源;
  • href为资源请求地址;
  • onload和onerror则分别是资源加载成功和失败后的回调函数;

其中 as 的值可以取style、script、image、font、fetch、document、audio、video等;
如果as属性被省略,那么该请求将会当做异步请求处理;

另外,在请求跨域资源时推荐加上crossorigin属性,否则可能会导致资源的二次加载(尤其是font资源):

<link rel="preload" as="font" href="www.font.com" crossorigin="anonymous">
<link rel="preload" as="font" href="www.font.com" crossorigin="use-credentials">

preload特点

  • preload加载的资源是在浏览器渲染机制之前进行处理的,并且不会阻塞onload事件;
  • preload可以支持加载多种类型的资源,并且可以加载跨域资源;
  • preload加载的js脚本其加载和执行的过程是分离的。即preload会预加载 相应的脚本代码,待到需要时自行调用;

prefetch

  • prefetch是一种利用浏览器的空闲时间加载页面将来可能用到的资源的一种机制;
  • 通常可以用于加载非首页的其他页面所需要的资源,以便加快后续页面的首屏速度;

prefetch特点

  • pretch加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少5分钟(无论资源是否可以缓存);
  • 当页面跳转时,未完成的prefetch请求不会被中断;

对比

  • 相同点:

Chrome有四种缓存:http cache、memory cache、Service Worker cache和Push cache。

在preload或prefetch的资源加载时,两者均存储在http cache。

当资源加载完成后,如果资源是可以被缓存的,那么其被存储在http cache中等待后续使用;

如果资源不可被缓存,那么其在被使用前均存储在 memory cache。

  • preload和prefetch都没有同域名的限制;
  • preload主要用于预加载当前页面需要的资源;而prefetch主要用于加载将来页面可能需要的资源;
  • 不论资源是否可以缓存,prefetch会存储在net-stack cache至少5分钟;
  • preload需要使用as属性指定特定的资源类型以便浏览器为其分配一定的优先级,并能够正确加载资源。

webpack中通过注释

通过添加内联的注释赋予import()动态加载语法更多实用的特性,比如给chunk命名,使用不同的webpackMode,prefetch,preload 等。

import(

/* webpackInclude: /\.json$/ */

/* webpackExclude: /\.noimport\.json$/ */

/* webpackChunkName: "my-chunk-name" */ `赋予 chunk 指定的名字`

/* webpackMode: "lazy" */ `这个是默认值使用import(),你什么也不加webpackMode就为 lazy`

/* webpackPrefetch: true */ `赋予 chunk prefetch能力`

/* webpackPreload: true */ `赋予 chunk preload能力`

./locale/${language} // 引用路径可以使用变量

);