参考
Preload,Prefetch 和它们在 Chrome 之中的优先级
对以下文章的补充
图片处理
预加载,在onload之后动态插入img标签,使浏览器提前缓存该图片
懒加载,使用onload之后手动设置src,src的值存放在标签的某个属性上即可(如data-x-src),实现策略:滚动监听、节流函数、手动设置src值
模块处理:
dns预解析
当浏览器真正请求该域中的某个资源时,DNS 的解析就已经完成了
<link rel="dns-prefetch" href="//example.com">
tcp预连接
预先建立 socket 连接,从而消除昂贵的 DNS 查找、TCP 握手和 TLS 往返开销
<link rel="preconnect" href="http://example.com">
资源预获取
优先级低,那就意味着浏览器空闲的时候才会对资源进行获取(但也可能不获取,即被浏览器忽略),可轻松绕过性能瓶颈。下载的资源一般用于将来的页面,而不是当前页面
<link rel="prefetch" href="image.png">
预渲染
会预处理这个页面中所有的资源,慎重使用;确保用户会访问这个链接,才去预渲染,否则可能浪费较多资源(高流量、高cpu)。
<link rel="prerender" href="http://example.com">
应用场景:用户精确搜索出一个结果,那可以预渲染这个页面链接;阅读中,预渲染下一个页面的内容。
prefetch
<link rel=“prefetch”>
告诉浏览器加载下一页面可能会用到的资源,因为资源是作用于下一个页面,所以优先级很低
preload
<link rel="preload">
加载的资源作用于当前页面。浏览器可以正确指定优先级,即preload不会影响当前页面重要资源的下载;和prefetch不同的是,prefetch可能会被浏览器忽略,但浏览器必定会响应preload
有as属性,常用的值有:script、style、image、media、document。忽略as属性的话,preload等同于xhr请求,优先级较低
资源都是异步下载,不会阻碍window.onload的触发,拥有自己的onload事件(至少对于chrome,prefetch没有onload事件)。注意:script async会阻塞onload
应用场景
加载字体。因为字体对界面很重要,而且埋在css中,不知道对应的选择器什么时候才会作用到dom节点上,这时候预先加载字体可以提升速度和用户体验(crossorigin 是必须的即使资源没有跨域)
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
加载资源但不执行。
<link rel="preload" href="late_discovered_thing.js" as="script">
脚本化操作
var preload = document.createElement("link");
link.href = "myscript.js";
link.rel = "preload";
link.as = "script";
document.head.appendChild(link);
加载后马上执行
<link rel="preload" as="style" href="async_style.css" onload="this.rel='stylesheet'">
对于js
<link rel="preload" as="script" href="async_script.js"
onload="var script = document.createElement('script');
script.src = this.href;
document.body.appendChild(script);">
prefetch用于加载其他页面可能要用到的资源,而preload用于加载这个页面将要用到的资源
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Faster</title> <link rel="dns-prefetch" href="//cdn.com/"> <link rel="preload" href="//js.cdn.com/currentPage-part1.js" as="script"> <link rel="preload" href="//js.cdn.com/currentPage-part2.js" as="script"> <link rel="preload" href="//js.cdn.com/currentPage-part3.js" as="script"> <link rel="prefetch" href="//js.cdn.com/prefetch.js"> </head> <body> <script type="text/javascript" src="//js.cdn.com/currentPage-part1.js" defer></script> <script type="text/javascript" src="//js.cdn.com/currentPage-part2.js" defer></script> <script type="text/javascript" src="//js.cdn.com/currentPage-part3.js" defer></script> </body> </html>
响应式的加载
<link rel="preload" as="image" href="map.png" media="(max- 600px)"> <link rel="preload" as="script" href="map.js" media="(min- 601px)">
检查浏览器是否支持preload
参考:https://github.com/w3c/preload/issues/7
var DOMTokenListSupports = function(tokenList, token) { if (!tokenList || !tokenList.supports) { return; } try { return tokenList.supports(token); } catch (e) { if (e instanceof TypeError) { console.log("The DOMTokenList doesn't have a supported tokens list"); } else { console.error("That shouldn't have happened"); } } }; var linkSupportsPreload = DOMTokenListSupports(document.createElement("link").relList, "preload"); if (!linkSupportsPreload) { // Dynamically load the things that relied on preload. }
终极完美的结构
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Faster</title> <link rel="dns-prefetch" href="//cdn.cn/"> <!--预加载当前页面的资源--> <link rel="preload" href="//cdn.cn/webfont.woff2" as="font"> <link rel="preload" href="//cdn.cn/Page1-A.js" as="script"> <link rel="preload" href="//cdn.cn/Page1-B.js" as="script"> <!--预加载其他页面的js--> <link rel="prefetch" href="//cdn.cn/Page2.js"> <link rel="prefetch" href="//cdn.cn/Page3.js"> <link rel="prefetch" href="//cdn.cn/Page4.js"> <style type="text/css"> /* 首页用到的CSS内联 ,这里用到字体*/ </style> </head> <body> <script type="text/javascript" src="//cdn.cn/Page1-A.js" defer></script> <script type="text/javascript" src="//cdn.cn/Page1-B.js" defer></script> </body> </html>
。