都放假了吧,祝你们春节快乐,没对象的都相亲成功,有对象的也相亲成功~javascript
网页渲染过程:css
上面的过程是由 GUI 渲染线程完成的。html
浏览器内有多个进程,其中渲染进程被称为浏览器内核,负责页面渲染和执行 JS 脚本等。渲染进程负责浏览器的解析和渲染,内部有 JS 引擎线程、 GUI 渲染线程、事件循环管理线程、定时器线程、HTTP 线程。java
JS 引擎线程负责执行 JS 脚本,GUI 渲染线程负责页面的解析和渲染,二者是互斥的,也就是执行 JS 的时候页面是中止解析和渲染的。这是由于若是在页面渲染的同时 JS 引擎修改了页面元素,好比清空页面,会形成后续页面渲染的没必要要和错误。而因为 JS 常常要操做 DOM ,就要涉及 JS 引擎线程和 GUI 渲染线程的通讯,而线程间通讯代价是很是昂贵的,这也是形成 JS 操做 DOM 效率不高的缘由。jquery
本文例子须要在控制台切换到弱网且无缓冲模式下进行测试: npm
浏览器的 HTML/CSS 的解析和渲染都属于 GUI渲染线程,因此和 JS 引擎线程是互斥、阻塞的。下面从代码实际运行的角度分析浏览器解析和渲染的顺序,以及互相间的阻塞关系:bootstrap
<button class="btn btn-primary">test1</button>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
<div>test2</div>
复制代码
alert('ok')
在 css 下载并解析完成以前不会弹出来:<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
<script> alert('ok') </script>
复制代码
alert('ok')
会在 css 下载完成前弹出:<script> alert('ok') </script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
复制代码
因此在须要提早执行不操做 dom 元素的 js 时,不妨把 js 放到 css 文件以前。浏览器
js 文件的下载和解析会阻塞 GUI 渲染进程,也就是会阻塞 DOM 和 CSS 的解析和渲染。网络
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<div>test</div>
复制代码
<div>test</div>
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
复制代码
第一,GUI 渲染线程会尽量早的将内容呈现到屏幕上,并不会等到全部的 HTML 都解析完成以后再去构建和布局 Render Tree,而是解析完一部份内容就显示一部份内容,同时,可能还在经过网络下载其他内容。下面 test1 会在 js 文件下载完成前渲染完成,而 test2 则会在 js 文件下载并执行完以后渲染:dom
<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/bootstrap@4.4.1/dist/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
</body>
复制代码
总之,无论是下载 js 文件仍是 css 文件,都会阻塞下面页面的渲染,但不会阻塞前面的渲染,符合咱们预期的编码逻辑。