网页资源阻塞浏览器加载的原理示例解析 - 网站

网页资源阻塞浏览器加载的原理示例解析

分类:前端开发知识_WEB开发技术文章 · 发布时间:2023-03-13 16:36 · 阅读:6250

这篇文章主要为大家介绍了网页资源阻塞浏览器加载的原理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

一个页面允许加载的外部资源有很多,常见的有脚本、样式、字体、图片和视频等,对于这些外部资源究竟是如何影响整个页面的加载和渲染的呢?今天来一探究竟。

  • 如何用 Chrome 定制网络加载速度?
  • 图片/视频/字体会阻塞页面加载吗?
  • CSS 是如何阻塞页面加载的?
  • JS 又是如何阻塞页面加载的?
  • JS 一定会阻塞 DOM 加载吗?
  • defer 和 async 是什么?又有何特点?
  • 动态脚本会造成阻塞吗?
  • 阻塞是怎么和 DOMContentLoaded 与 onload 扯上关系的?

测试前环境准备

测试之前需要对浏览器下载资源的速度进行控制,将它重新设置为 50kb/s,操作方式:

  • 打开 Chrome 开发者工具;
  • 在 Network 面板下找到 Disable cache 右侧的下拉列表,然后选择 Add 添加自定义节流配置;
  • 添加一个下载速度为 50kb/s 的配置;
  • 最后在第二步骤中的下拉列表选择刚刚配置的选项即可;
  • 注意:如果当前选择的自定义选项被修改了,则需要切换到别的选项再切回来才可生效。

为什么是这个速度?因为如下的一些资源,比如图片、样式或者脚本体积都是 50kb 的好几倍,方便测试。

图片会造成阻塞吗?

直接写个示例来看下结果:

   

我是 h1 标签

我是 h2 标签

上面这张图片的大小大概是 200kb,当把网络下载速度限制成 50kb/s,打开该页面,可以看到如下结果:当 h1h2 标签渲染出来且打印了 DOMContentLoaded 的时候,此时图片还在加载中,这就说明了图片并不会阻塞 DOM 的加载,更加不会阻塞页面渲染;当图片加载完成的时候,会打印 onload,说明图片延迟了 onload 事件的触发。
视频、字体和图片其实是一样的,也不会阻塞 DOM 的加载和渲染。

CSS 加载阻塞

同样的,还是直接用代码来测试 CSS 加载对页面阻塞的情况,因为下面代码加载的 bootstrap.css 是 192kb 的,所以理论上下载它应该需要花费 3 到 4 秒左右。

   

我是 h1 标签

测试过程如下:

  • Elements 面板下,选中 h1 这个标签,然后按 delete 键将它从 DOM 中删掉,从而模拟首次加载;
  • 刷新浏览器,马上 Elements 面板下就加载出 h1 标签,继续加载 3 到 4 秒后(此时正在加载 bootstrap.css),页面出现 我是 h1 标签 字样,此时页面已经渲染完成。

从而得出结论:

  • bootstrap.css 还没加载完成,而 DOM 中就已经出现 h1 标签,说明 CSS 不会阻塞 DOM 的解析;
  • 页面直到 bootstrap.css 加载完成才出现 h1 里的文案,说明 CSS 会阻塞 DOM 的渲染。

为什么是这个结论呢?试想一下页面渲染的流程就知道了。浏览器首先解析 HTML 生成 DOM 树,解析 CSS 生成 CSSOM 树,然后 DOM 树和 CSSOM 树进行合成生成渲染树,通过渲染树进行布局并且计算每个节点信息,绘制页面。


可以说解析 DOM 和 解析 CSS 其实是并列进行的,既然是并列进行的,那 CSS 和 DOM 就不会互相影响了,这和结论一相符;另外渲染页面一定是在得到 CSSOM 树之后进行的,这和结论二相符。
CSS 一定会阻塞 DOM 的渲染嘛?答案是否定的,当把外链样式放到 最尾部去加载:

 

我是 h1 标签

此时刷新浏览器,页面上会马上显示出 我是 h1 标签 字样,当 3 到 4 秒过后样式加载完成的时会造成二次渲染,页面重新渲染出该字样,这就说明 CSS 阻塞 DOM 的渲染只阻塞定义在 CSS 后面的 DOM。二次渲染会对用户造成不好的体验且加重了浏览器的负担,所以这也就是为什么需要把外链样式提前到 里加载的原因。

CSS 会阻塞后面 JS 的执行吗?

CSS 阻塞了后面 DOM 的渲染,那它会阻塞 JS 的执行嘛?

   

我是 h1 标签

刷新浏览器的时候可以看到,浏览器 Console 面板下没有打印内容,而当样式加载完成的时候打印了 888,这就说明 CSS 会阻塞定义在其之后 JS 的执行。

为什么会这样呢?试想一下,如果 JS 里执行的操作需要获取当前 h1 标签的样式,而由于样式没加载完成,所以就无法得到想要的结果,从而证明了 CSS 需要阻塞定义在其之后 JS 的执行。

JS 加载阻塞

CSS 会阻塞 DOM 的渲染和阻塞定义在其之后的 JS 的执行,那 JS 加载会对渲染过程造成什么影响呢?

   

我是 h1 标签

首先删除页面中已经存在的 h1 标签(如果存在的话),仔细观察 Elements 面板,当刷新浏览器的时候,一直未加载出 h1 标签(期间页面一直白屏),直到 JS 加载完成后,DOM 中才出现,这足以说明了 JS 会阻塞定义在其之后的 DOM 的加载,所以应该将外部 JS 放到 的最尾部去加载,减少页面加载白屏时间。

defer 和 async

JS 一定会阻塞定义在其之后的 DOM 的加载吗?来测试一下:

   

我是 h1 标签

上面这段代码的测试结果是当页面中显示出 h1 标签的时候,脚本还没有加载完成,这就说明了 async 脚本不会阻塞 DOM 的加载;同理可以用同样的方式测试 defer,也会得到这个结论。

现在知道了通过 defer 或者 async 方式加载 JS 的时候,它是不会阻塞 DOM 加载的。知道 deferasync 是什么吗?它们两者有什么区别呢?

回答这些疑问之前,先来看下当浏览器解析 HTML 遇到 script 标签的时候会发生什么?

  • 暂停解析 DOM;
  • 执行 script 里的脚本,如果该 script 是外链,则会先下载它,下载完成后立刻执行;
  • 执行完成后继续解析剩余 DOM。

上面这是解析时遇到一个正常的外链的情况,正常外链的下载和执行都会阻塞页面解析;而如果外链是通过 defer 或者 async 加载的时候又会是如何呢?

defer 特点

  • 对于 deferscript,浏览器会继续解析 html,且同时并行下载脚本,等 DOM 构建完成后,才会开始执行脚本,所以它不会造成阻塞;
  • defer 脚本下载完成后,执行时间一定是 DOMContentLoaded 事件触发之前执行;
  • 多个 defer 的脚本执行顺序严格按照定义顺序进行,而不是先下载好的先执行;

async 特点

  • 对于 asyncscript,浏览器会继续解析 html,且同时并行下载脚本,一旦脚本下载完成会立刻执行;和 defer 一样,它在下载的时候也不会造成阻塞,但是如果它下载完成后 DOM 还没解析完成,则执行脚本的时候是会阻塞解析的;
  • async 脚本的执行 和 DOMContentLoaded 的触发顺序无法明确谁先谁后,因为脚本可能在 DOM 构建完成时还没下载完,也可能早就下载好了;
  • 多个 async,按照谁先下载完成谁先执行的原则进行,所以当它们之间有顺序依赖的时候特别容易出错。 :::info deferasync 都只能用于外部脚本,如果 script 没有 src 属性,则会忽略它们。 :::

动态脚本会造成阻塞吗?

对于如下这段代码,当刷新浏览器的时候会发现页面上马上显示出 我是 h1 标签,而过几秒后才加载完动态插入的脚本,所以可以得出结论:动态插入的脚本不会阻塞页面解析。

我是 h1 标签

动态插入的脚本在加载完成后会立即执行,这和 async 一致,所以如果需要保证多个插入的动态脚本的执行顺序,则可以设置 script.async = false,此时动态脚本的执行顺序将按照插入顺序执行和 defer 一样。

DOMContentLoaded 和 onload

在浏览器中加载资源涉及到 2 个事件,分别是 DOMContentLoadedonload,那么它们之间有什么区别呢?

  • onload:当页面所有资源(包括 CSS、JS、图片、字体、视频等)都加载完成才触发,而且它是绑定到 window 对象上;
  • DOMContentLoaded:当 HTML 已经完成解析,并且构建出了 DOM,但此时外部资源比如样式和脚本可能还没加载完成,并且该事件需要绑定到 document 对象上;

一定看到了上面的可能二字,为什么当 DOMContentLoaded 触发的时候样式和脚本是可能还没加载完成呢?

DOMContentLoaded 遇到脚本

当浏览器处理一个 HTML 文档,并在文档中遇到

我是 h1 标签

那么一定是脚本执行完成后才会触发 DOMContentLoaded 嘛?答案也是否定的,有两个例外,对于 async 脚本和动态脚本是不会阻塞 DOMContentLoaded 触发的。

DOMContentLoaded 遇到样式

前面已经介绍到 CSS 是不会阻塞 DOM 的解析的,所以理论上 DOMContentLoaded 应该不会等到外部样式的加载完成后才触发,这么分析是对的,用下面代码进行测试一翻就知道了:

   

我是 h1 标签

测试结果:当样式还没加载完成的时候,就已经打印出 DOMContentLoaded,这和分析的结果是一致的。但是一定是这样嘛?显然不一定,这里有个小坑,(基于上面代码)在样式后面再加上

以上就是网页资源阻塞浏览器加载的原理示例解析的详细内容,更多关于网页资源阻塞浏览器加载的资料请关注0133技术站其它相关文章!

标签:
网页阻塞 浏览器 资源加载

相关文章

W3标准不变 清除浮动实现代码

对于日新月异的WEB开发技术和浏览器更新频率来说,清除浮动已然是一个被人嚼碎了的话题。说是这些年过去了,有关float的地方,还依然少不了清除浮动的标签和css代码

Web前端开发规范文档(css/javascript)

最近开始着手网站的改版,因为是团队协作,所有需要注意很多地方,也为了让我们的代码更加规范特收集了一些Web前端开发规范

重新封装的JQuery获取浏览器信息的代码

用JQuery代码获取浏览器信息的方法

让AJAX弹出提示信息效果的代码

AJAL弹出信息提示的代码

ASP.NET性能优化之负载均衡的方法

ASP.NET性能优化之负载均衡的代码

返回分类 返回首页