28

CSS 和 JS 阻塞二三事

 5 years ago
source link: https://juejin.im/post/5e23f027e51d454d94422f20
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
2020年01月22日 阅读 2589

CSS 和 JS 阻塞二三事

都放假了吧,祝大家春节快乐,没对象的都相亲成功,有对象的也相亲成功~

浏览器渲染步骤

网页渲染过程:

1
  1. 将 HTML 解析成 DOM Tree,同时将 CSS 解析成 CSSOM Tree
  2. 将 DOM Tree 和 CSSOM Tree 合并成 Render Tree
  3. 生成布局 Layout ,计算 Render Tree 中元素的尺寸、位置
  4. 将 Render Tree 绘制成像素点,最后显示在屏幕上

上面的过程是由 GUI 渲染线程完成的。

浏览器内核(渲染进程)

浏览器内有多个进程,其中渲染进程被称为浏览器内核,负责页面渲染和执行 JS 脚本等。渲染进程负责浏览器的解析和渲染,内部有 JS 引擎线程、 GUI 渲染线程、事件循环管理线程、定时器线程、HTTP 线程。

JS 引擎线程负责执行 JS 脚本,GUI 渲染线程负责页面的解析和渲染,两者是互斥的,也就是执行 JS 的时候页面是停止解析和渲染的。这是因为如果在页面渲染的同时 JS 引擎修改了页面元素,比如清空页面,会造成后续页面渲染的不必要和错误。而由于 JS 经常要操作 DOM ,就要涉及 JS 引擎线程和 GUI 渲染线程的通信,而线程间通信代价是非常昂贵的,这也是造成 JS 操作 DOM 效率不高的原因。

解析、渲染与阻塞

本文例子需要在控制台切换到弱网且无缓冲模式下进行测试:

1

浏览器的 HTML/CSS 的解析和渲染都属于 GUI渲染线程,所以和 JS 引擎线程是互斥、阻塞的。下面从代码实际运行的角度分析浏览器解析和渲染的顺序,以及互相间的阻塞关系:

CSS 阻塞

  1. css 文件的下载和解析不会影响 DOM 的解析,但是会阻塞 DOM 的渲染。因为 CSSOM Tree 要和 DOM Tree 合成 Render Tree 才能绘制页面。下面的 test1 在 css 下载并解析完成前是默认样式, test2 在 css 下载并解析完成之前不会显示:
<button class="btn btn-primary">test1</button>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<div>test2</div>
复制代码
  1. css 文件没下载并解析完成之前,后续的 js 脚本不能执行。下面的 alert('ok') 在 css 下载并解析完成之前不会弹出来:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<script>
    alert('ok')
</script>
复制代码
  1. css 文件的下载不会阻塞前面的 js 脚本执行。下面的 alert('ok') 会在 css 下载完成前弹出:
<script>
    alert('ok')
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
复制代码

所以在需要提前执行不操作 dom 元素的 js 时,不妨把 js 放到 css 文件之前。

js 文件的下载和解析会阻塞 GUI 渲染进程,也就是会阻塞 DOM 和 CSS 的解析和渲染。

  1. js 文件没下载并解析完成之前,后续的 HTML 和 CSS 无法解析:
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <div>test</div>
复制代码
  1. js 文件的下载不会阻塞前面 HTML 和 CSS 的解析:
    <div>test</div>
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
复制代码

需要注意的点

第一,GUI 渲染线程会尽可能早的将内容呈现到屏幕上,并不会等到所有的 HTML 都解析完成之后再去构建和布局 Render Tree,而是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。下面 test1 会在 js 文件下载完成前渲染完成,而 test2 则会在 js 文件下载并执行完之后渲染:

  <div>test1</div>
  <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
  <div>test2</div>
复制代码

第二,文件的下载是不会被阻塞的,不管是 css 还是 js 文件,浏览器的主线程会在页面解析前开启下载,所以就算在外部脚本执行前删除脚本,脚本也还是会下载。

<body>
  <script>
    document.body.remove()
  </script>  
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
</body>
复制代码

总之,不管是下载 js 文件还是 css 文件,都会阻塞下面页面的渲染,但不会阻塞前面的渲染,符合我们预期的编码逻辑。


Recommend

  • 240

    hello~各位亲爱的看官老爷们大家好。估计大家都听过,尽量将CSS放头部,JS放底部,这样可以提高页面的性能。然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付考核当然可以,但实际应用中必然一塌糊涂。因此洗(wang)心...

  • 107
    • 掘金 juejin.im 7 years ago
    • Cache

    大麦网技术二三事

    杭州周杰伦2017年项目,大麦网抢票系统抢瘫了,据传阿里内部炸了锅,大麦在阿里序列里直接进入了被鄙视链的第一名,江湖上也是声名狼藉。作为大麦故人,我已经是不止一次的在各种场合听到诸如“大麦网技术水平太烂了”、“大麦基本没什么技术含量”、“大麦的技术还处于...

  • 93
    • 微信 mp.weixin.qq.com 7 years ago
    • Cache

    美帝面试二三事

    美帝面试二三事 Original 已步入中老年的...

  • 65

    2017-12-18 09:35 摩拜街电猩便利,衣二三后多抓鱼:什么导致了它们的流行在这个时代,VC 到底还要不要找独角兽?到底还要不要追求百倍回报?跳开一切,从 LP(出资人)的角度来说,我觉得还是要的。...

  • 68
    • 微信 mp.weixin.qq.com 7 years ago
    • Cache

    缓存实战二三事

    缓存实战二三事 丁浪...

  • 90
    • 掘金 juejin.im 7 years ago
    • Cache

    跨域实践二三事

    文章首发 跨域是日常开发中经常开发中经常会接触到的一个重难点知识,何不总结实践一番,从此心中对之了无牵挂。 同源策略 之所以会出现跨域解决方案,是因为同源策略的限制。同源策略规定了如果两个 url 的协议、域名、端口中有任何一个不等,就认定它们跨源了。...

  • 52

    二三四五发布2017年度业绩快报,在这份报告中,2017年未经审计的净利润为9.32亿元。与此同时,该公司还公告了一项总额高达9.64亿元的资产减值。

  • 41

    对于普通人来说,只能用努力抢救学历

  • 34
    • 掘金 juejin.im 6 years ago
    • Cache

    css加载会造成阻塞吗?

    之前面试今日头条的时候,今日头条面试官问我,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?所以,接下来我就来对css加载对DOM树的解析和渲染做一个测试。 为了完成本次测试,先来科普一下,如何利用chrome来设置下载速度

  • 4

    给「Cards」主题的导航栏做下拉菜单已经是好几个版本之前(v0.5)的事情了,由于特殊一些特殊癖好一直没有引入 J...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK