精读《高性能JavaScript》 – 无阻塞的脚本

javascript/jquery

浏览数:15

2020-5-19

AD:资源代下载服务

首发个人网站《锋言锋语》- 精读《高性能JavaScript》 – 无阻塞的脚本

JavaScript’s tendency to block browser processes, both HTTP requests and UI updates, is the most notable performance issue facing developers.

JavaScript倾向于阻止浏览器的某些处理过程,如HTTP请求和用户界面更新,这是开发者所面临的最显著的性能问题

这里提到JavaScript执行会阻止以下几方面的处理过程:

  • HTTP请求
  • 用户界面更新

JavaScript执行会阻止‘用户界面更新’?

有以下几段代码:

<body>
    <p >Hello World</p>
</body>

在chrome下通过性能工具可以得到以下的加载序列图:

从图中我们可以得到以下信息:

  • 从显示上分为三个阶段:

    • 第一阶段:网络加载资源,属于 Idle Frame
    • 第二阶段:解析HTML和布局,属于 Frame
    • 第三阶段:内容显示到界面上

接下来,我们分别在p标签前后加一小段script代码,然后再在chrome下通过性能工具可以得到各自的加载序列图:

<body>
    <script>
        for (var i = 0, len = Math.pow(2, 27); i < len; i++) {}
    </script>
    <p >Hello World</p>
</body>
<body>
    <p >Hello World</p>
    <script>
        for (var i = 0, len = Math.pow(2, 27); i < len; i++) {}
    </script>
</body>


通过对比截图可以得到以下信息:

  • 无论script代码是在p的前面还是后面,在渲染过程中都会阻塞渲染部分,导致First Paint的时间延后
  • 引起阻塞的原因是script代码的执行是包含在 Parse HTML 这个 Task 中的

因此:JavaScript执行会阻止‘用户界面更新’这个说法是可以得到印证的。

JavaScript执行会阻止‘HTTP请求’?

关于这个结论,我通过以下代码做了测试,首先观察只有HTTP请求时的代码和加载序列图:

<body>
    <img src="./sample.jpg">
</body>

在chrome下通过性能工具可以得到以下的加载序列图:

可以看到在 Parse HTML 阶段就异步进行网络请求,网络请求的时间并没有阻塞 Parse HTML 这个任务。

接下来,我们分别在img标签前后加一小段script代码,然后再在chrome下通过性能工具可以得到各自的加载序列图:

<body>
    <script>
        for (var i = 0, len = Math.pow(2, 27); i < len; i++) {}
    </script>
    <img src="./sample.jpg">
</body>
<body>
    <img src="./sample.jpg">
    <script>
        for (var i = 0, len = Math.pow(2, 27); i < len; i++) {}
    </script>
</body>


通过对比截图可以得到以下信息:

  • 无论script代码是在img的前面还是后面,真正的 JavaScript 执行阶段都是在 HTTP 请求之后,并不会阻塞 HTTP 请求
  • 不会阻塞的原因是因为, Parse HTML 任务只是异步通知其它进程进行网络请求,并不会阻塞自身的进程逻辑

在上述示例中,由于图片文件较小,HTTP 请求的时间较短,无法明确看出异步进行网络请求的效果,下面使用一个大文件进行网络验证:

<body>
    <img src="./largeFile.jpg">
    <script>
        for (var i = 0, len = Math.pow(2, 27); i < len; i++) {}
    </script>
</body>

通过上述截图可以清晰看到:HTTP 网络请求和 JavaScript 执行是并发进行的,相互不会产生阻塞。

因此:JavaScript执行会阻止‘HTTP请求’这个说法是错误的,已经过时的。

作者:NferZhuang