在下载了文本文档之后,在 parse HTML 之前就开始请求带有 rel="preload" ,好家伙,这个优先级确实够高的,不过要注意,这里只是提前加载,加载完后会将他们存储在浏览器的缓存中,并不会马上执行(js),等 parse HTML 的时候,解析到对应的资源标签,再从缓存中获取。
如果说不用 preload 那文件啥时候加载呢,理论上是在 parse HTML 之后,因 html 是逐行解析的,所以,当解析到 js、 css 对应的 script 和 link 标签时才会去请求加载。为了验证下这个想法,把 html 里面的 preload 都去掉之后,再看下(用anywhere本地起个服务,上张图是用的线上测试环境的,所有有些加载时间会不太一样,这里只是验证想法)
在做项目优化的时候,遇到了
prefetch
、preload
,之前没有总结过,所以今天顺带都总结下。首先这些属性都是在
link
标签上使用,以前都是拿link
标签来加载外部css,没想到还有这个妙用。preload
示例代码
作用 (提前加载)
preload 是一个
高优先级
的资源加载声明,专注于当前页面。通过 Chrome devtools 的 network 面板,可以看到带有
<link rel="preload">
的资源会优先发送加载的请求。那么到底会优先到啥程度呢? MDN 是这么说的
主渲染机制介入前?有点抽象啊,没关系,我们用 chrome 的Performance 来形象的看一下,如图
在下载了文本文档之后,在 parse HTML 之前就开始请求带有
rel="preload"
,好家伙,这个优先级确实够高的,不过要注意,这里只是提前加载,加载完后会将他们存储在浏览器的缓存中,并不会马上执行(js)
,等 parse HTML 的时候,解析到对应的资源标签,再从缓存中获取。如果说不用
preload
那文件啥时候加载呢,理论上是在 parse HTML 之后,因 html 是逐行解析的,所以,当解析到 js、 css 对应的 script 和 link 标签时才会去请求加载。为了验证下这个想法,把 html 里面的 preload 都去掉之后,再看下(用anywhere本地起个服务,上张图是用的线上测试环境的,所有有些加载时间会不太一样,这里只是验证想法)通过两张图的对比,应该能很清晰的看出来区别了吧。
支持哪些类型的内容预加载
其他优点:
兼容性:
再通过caniuse看下兼容性,覆盖率92%,可以放心用。
prefetch
示例代码
作用 (预判加载)
prefetch 是低优先级的资源加载声明,主要是利用浏览器空闲时间来下载后续页面或者之后要用到的资源。
浏览器的空闲时间如何确定的?
这个说法也太不好理解了,还是直接看实际的例子吧 这个是页面代码:
来看下加载的顺序:
这么看貌似没什么问题,符合预期,确实是在这几个请求之后开始的。
但是在 vue 的项目中,会根据当前页面的路由动态生成几个这种标签(所谓的路由懒加载),比如首页组件对应的css、js。如下图:
再看下请求顺序:
因为这几个标签是 app.js 动态添加的,在这之前,浏览器已经判定为空闲时间,已经开始了下载任务。
如果是用的 http1.1,开启了长连接(connection:keep-alive)的情况下,会有http 队头阻塞问题,在已经有几百个prefetch 在请求的情况下,tcp 所有的通道已经被占用了,所以首页的资源只能等待他们下载完再开始。
如果是用的http2.0,首页的资源请求跟prefetch 在同一个tcp通道传输,假如有丢包,则会影响后面的资源加载;prefetch 的优先级是 lowest,首页资源的js 是 low, css 是highest,不知道浏览器在同时下载的时候,会不会优化高优先级的资源(有知道的小伙伴可以告诉我,谢谢)。正常情况下,他们属于带宽竞争关系。不管怎样,prefetch 都会抢占首页的加载资源。
所以为了提高首屏速度,还是把 prefetch 去掉或者 将 prefetch 用js动态延迟加载。
兼容性:
dns-prefetch
作用 (dns 预解析)
dns-prefetch 主要是为后面要加载的文件或打开的链接提供提前解析域名的功能。
dns解析时间对比
dns 解析时间其实挺影响首屏页面加载速度的,不过在说这个问题之前还是要搞懂dns解析流程
其实不同网站dns 解析时间是不太一样的,比如淘宝、京东、知乎之类的大网站,在本地dns 服务器或者dns根、dns顶级域名服务器一般是有缓存的,所以他们的查询流程会比小网站短,所以查询速度会快一些,那dns解析速度一般会是多少呢,我们找几个网站对比一下看看 京东:
https://davidwalsh.name/html5-prefetch(之前没有访问过的网站):
经常访问的大网站的dns解析时间一般在20-30ms 左右,而没怎么访问过的小网站需要200-300ms左右,相差10倍左右,如果单是dns解析就要300ms的话,首屏做到1s内难度就更高一些了,所以首屏的资源最好放在同域名下,这样会省去后续资源的dns解析时间。
应用场景
兼容性:
prerender
作用
prerender 和 prefetch 相似,它们都会在空闲时间加载之后可能会用到的资源,区别是 prerender 在后台渲染了整个页面所有的资源。如下:
Steve Souders 的文章详细解释了这个技术:
在当前页面的dev tools 中是看不到 test.html 资源加载的,但是当跳转到 test.html 页面之后,会看到资源是缓存过的。
兼容性:
preconnect
作用
和 DNS prefetch 类似,preconnect 不光会解析 DNS,还会建立 TCP 握手连接和 TLS 协议(如果需要)。用法如下:
Ilya Grigorik 写了一篇文章详细说明了这种技术:
大佬的解释比 MDN 好太多了,膜拜!!!
这个真的是牛啊,直接把资源下载前的工作全干了,只需要等待资源下载就行了。 来看下使用前后网络请求对比图:
但是声明了 preconnect 不代表浏览器一定会去做,浏览器也可以选择忽略的(可能没有好的时机来处理,这完全可以取决于浏览器具体的实现)。
兼容性:
参考: https://developer.mozilla.org/zh-CN/docs/orphaned/Web/HTML/Preloading_content http://www.alloyteam.com/2015/10/prefetching-preloading-prebrowsing/ https://zhuanlan.zhihu.com/p/33179052