js阻塞浏览器ui渲染

本文探讨了JavaScript脚本加载与执行对浏览器UI渲染的影响。不带defer或async属性的脚本会同步加载,阻塞HTML解析;而带有defer或async的脚本异步加载,不阻碍HTML解析。无论哪种方式,脚本执行都会阻塞浏览器UI渲染,包括DOM树构建、CSS树构建等过程。测试验证了这些结论。

js加载与执行阻塞浏览器ui渲染

前言

我们都知道,javascript 脚本应该放置在 html 文档的底部,其实这只是个比较保险的做法,要想javascript 脚本不会阻塞浏览器 ui 的渲染,需要知道以下 javascript 脚本加载与执行对 ui 渲染的影响。

先上结论

下面结论针对外链脚本,在此之前应该明白两个概念,加载 和 执行,加载就是下载到本地,执行就是运行脚本。

  1. 若脚本标签不带 defer 或者 async 属性,则脚本属于同步加载,此时脚本加载会阻塞浏览器解析 html 文档。
  2. 若脚本标签带 defer 或者 async ,则脚本属于异步加载,此时脚本加载不会阻止浏览器解析 html 文档。
  3. 脚本执行都会阻塞浏览器 ui 渲染(dom树构建,css树构建,渲染树构建,重排,重绘)。
  4. 在浏览器中 javascipt 和 ui 渲染公用一个线程,但是下载的时候浏览器会有一个线程池维护一些 io操作(网络IO,磁盘IO),所以下载的时候通过设置可以不阻塞 ui 渲染。

在此说一下, defer 和 async 的相同点在于 都是异步加载脚本,区别在于 async 加载完会立即执行,而 defer 是在 dom 树解析(仅仅是dom结构,不管样式表,图片这些)之后执行。

测试

针对上面的结论,我们挨个测试。

1. 若脚本标签不带 defer 或者 async 属性,则脚本属于同步加载,此时脚本加载会阻塞浏览器解析 html 文档。

看下面代码 html:

<!-- demo.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="http://localhost/study/add.php" ></script>
    <style>
        .box {
            width: 400px;
            height: 400px;
            background: yellow;
        }
    </style>
</head>
<body>
    <div class="box">1ddd2223fff3f1</div>

</body>
</html>

add.php

<?php

sleep(2);

将php 放到网站根目录下,打开 demo.html 即可测试,在此我们看到 add.php 返回的脚本大小很小,但是我们通过 sleep 模拟加载慢的情况,也就是延长加载时间,我们打开浏览器可以看到,经过一段时间后 页面上才渲染出 box 元素。

2. 若脚本标签带 defer 或者 async ,则脚本属于异步加载,此时脚本加载不会阻止浏览器解析 html 文档

看下面代码:

<!-- demo.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="http://localhost/study/add.php"  defer ></script>
    <style>
        .box {
            width: 400px;
            height: 400px;
            background: yellow;
        }
    </style>
</head>
<body>
    <div class="box">1ddd2223fff3f1</div>

</body>
</html>

add.php

<?php

sleep(2);

我们给 script 标签加上 defer 或者 async ,打开浏览器看看,可以看到,box 元素瞬间显示在页面上。

3. 脚本执行都会阻塞浏览器 ui 渲染(dom树构建,css树构建,渲染树构建,重排,重绘)。

看下面代码:html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="demo1.js"></script>
    <style>
        .box {
            width: 400px;
            height: 400px;
            background: yellow;
        }
    </style>
</head>
<body>
    <div class="box">1ddd2223fff3f1</div>

</body>
</html>

demo1.js

let count = 0;
for (let i = 0; i < 1000000000; i ++) {
    count ++;
}

打开浏览器我们发现,浏览器会过一段时间才会显示 box 元素,在这里我们通过大量计算,占用了线程,因为浏览器中 ui渲染和 javascript 公用一个线程,所以会阻塞。

最后

献上一张图(盗的)-.-
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值