1987WEB视界-分享互联网热门产品和行业

您现在的位置是:首页 > 网络工具 > 正文

网络工具

入门基础知识点:浏览器到底是如何下载资源的

1987web2023-11-21网络工具161
天文章来聊聊浏览器到底是如何对待下载资源的,比如说JS、CSS、字体、图片等文件。CSS、JS文件冤家路窄HTML在解析的过程中遇到同步的

天文章来聊聊浏览器到底是如何对待下载资源的,比如说 JS、CSS、字体、图片等文件。CSS、JS 文件冤家路窄HTML 在解析的过程中遇到同步的script会卡住 DOM 解析这个知识点我相信读者们应该都知道。

1
上述代码中,HTML 遇到代码就会停止 DOM 解析了。当然现代浏览器不是说就这样停住啥也不干了,会有个 preload scanner 去扫描底下的文件,然后根据文件类型去制定优先级(这个下面再说)。上面举得例子是内联代码,如果是一个 JS 文件的话,那么就得等这个 JS 文件下完以后执行代码才行。但是一般我们文件结构不会那么单一,CSS 文件也肯定是有的。因为 JS 不仅能动 DOM 也能改 style,所以如果遇到script之前还有别的 CSS 文件的话,浏览器还得等 CSS 文件下完以后再去执行 JS。所以说不只是 JS 会阻塞 DOM 解析,CSS 也会。当然我想现在应该很少再有人直接写同步的script了吧。文件同时遇到,那会同时开始下载嘛?举个例子,在可以同时下载多个文件的情况下,浏览器在 HTML、CSS 文件中解析到了 img、font、background-image 资源,那么们会同时开始下载嘛?答案是不会!这里只有 img 会最先开始下载,其它两块内容都得等到 layout 以后才会开始下载。不信的话我们来看图:这里以 font 为例

图中右下角框出来的是字体文件,上面是 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 服务商了。最后

查找了很多资料,如有遗漏,还请见谅。文中如果有误,还望及时指出,感谢