入门基础知识点:浏览器到底是如何下载资源的
天文章来聊聊浏览器到底是如何对待下载资源的,比如说 JS、CSS、字体、图片等文件。CSS、JS 文件冤家路窄HTML 在解析的过程中遇到同步的script会卡住 DOM 解析这个知识点我相信读者们应该都知道。
图中右下角框出来的是字体文件,上面是 CSS 文件,字体是从 CSS 文件中得知需要去加载的。大家可以在图中发现 CSS 文件早早开始下载解析了,但是 font 文件迟迟未开始下载,直到 FP 指标即将出现的时候才开始下载动作,这个时间点是在 layout 完成以后。图中是以掘金为例,大家可以多试试别的网站,应该能发现是符合预期的。那么读者可能会有个疑问,按照这个逻辑意思是说能用 img 的都用 img,因为background-image 不是马上开始下载的?道理是这个道理,但是还是得分情况来说,如果图片出现的位置不是首屏,用 background-image 也没啥问题,当然给 img 用上懒加载也能解决问题。那么到底文件的优先级是如何的?如果大家有使用过 Performance 测试网站性能的话,可以在 Network 那栏里 hover 下载的资源,此时你能发现资源有优先级的显示。
从图中大家可以发现 CSS 和字体资源的优先级的最高的,JS 文件有高有低(这和类型有关),图片、svg 的优先级为低。这部分的优先级是指某个时间点上的优先级,而不是适应于整个周期。对于 CSS 文件优先级最高还是挺好理解的,毕竟 JS 文件依赖于 CSS 文件,更加详细的内容大家可以参考 从Chrome源码看浏览器如何加载资源 中的「3. 资源优先级」内容。网络协议才是最大元凶浏览器要下载资源,TCP 协议肯定得用上,但是 TCP 协议天生就是一个慢的东西。先得握手,然后慢开始算法,就和我们用迅雷下载东西一样,带宽很大没用,速度都是得爬升上去的。如果再加个 HTTPS 的话,还得再多个 TLS 的握手。然后说回 HTTP1.1 协议。Chrome 只支持同个 domain 同时并发 6 个请求,所以在之前的协议中一堆请求都得 block 住等之前的下载完成。当然现在不同了,HTTP2 的概念基本大家都知道了,没见过猪跑但吃过猪肉,对于这块的知识点聊上几句没啥问题。什么多路复用,header 合并、二进制帧啥的。得利于 HTTP2 协议中的多路复用,我们不再被浏览器的六个并发所限制,所有同一个 domain 上的请求都能跑在复用的六个网络通道上,下载耗时瞬间减少了几个量级,但是大家有没有考虑过这个 HTTP2 到底是如何对待这些资源的?如何分配它们的优先级?依赖?带宽或者别的?毕竟一堆资源占用同一个网络通道,那么到底该谁先下载,谁享有的带宽多点都是需要协调的。否则假如一堆图片占用了大部分带宽,其他 CSS、JS 文件下的很慢的话,就会影响整个网页的性能了。比如说我现在需要下载 CSS、JS、图片和字体这些文件。举个例子在这些文件中我希望 CSS 文件能最先开始下载,并且能分配到的带宽多点;JS 文件呢可以等 CSS 文件下完再去下;其他文件呢优先级比 CSS 文件低点,但是也能够享受到带宽去进行下载。这个需求我们可以通过二进制帧去实现。HTTP2 协议共存在十个二进制帧,其中你可以通过 HEADERS 帧分配新的优先级,也可以通过 PRIORITY 帧更改优先级。对于流的优先级,我们可以通过两个方式来实现调整:
- 当我们调整流的依赖时,就可以实现让 JS 文件等待 CSS 文件下载完毕以后再开始
- 当我们调整流的 weight 时,就可以实现带宽的分配,让某些资源能更快地进行下载
如图所示(丑了点)。第一排的文件开始一起下载,weight 相加为 20,那么通过计算可得 CSS 文件享有带宽的一半,其他各占有 1 / 4,JS 文件得等 CSS 完成以后才开始。那么该如何设置这些东西呢?当然得服务端支持啦,一般都指 CDN 服务商了。最后
查找了很多资料,如有遗漏,还请见谅。文中如果有误,还望及时指出,感谢