在本文中:https://www.html5rocks.com/en/tutorials/speed/script-loading/
他们在说:
动态创建并添加到文档中的脚本默认是异步的,它们不会阻止渲染
但“执行javascript”总是阻塞渲染,那怎么能说不阻塞渲染呢?
我可以通过这个例子更清楚地说明:
脚本.JS
// Synchronous delay of 5 seconds
var timeWhile = new Date().getTime();
while( new Date().getTime() - timeWhile < 5000 );
索引.HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
<script>
['script.js'].forEach( function( src ) {
var script = document.createElement( 'script' );
script.src = src;
script.async = true;
document.head.appendChild(script);
});
// Some other javascript execution, let's say execution delay of 2 seconds.
var timeWhile = new Date().getTime();
while( new Date().getTime() - timeWhile < 2000 );
</script>
</head>
<body>
Some HTML line and this is above the fold
</body>
</html>
我在 Chrome 和 Firefox 中对其进行了测试,两种浏览器都在 7 秒后(而不是更早)显示:“一些 HTML 行,此行位于首屏上方”。所以 script.js 的执行会阻塞渲染,否则浏览器会在 2 秒后显示一些内容。
注意:您也可以不延迟2秒进行测试,但重复测试时可能会得到不同的结果。由于延迟了 2 秒,我给了浏览器一些额外的时间,因此我确信在完成渲染之前 script.js 已被下载。无论如何,您都可以获得相同的结果,而不会造成延迟,但这只是为了在这篇文章中更清楚地说明这一点。
这里发生了什么:
- 浏览器首先将创建元素(带有外部文件 script.js 的异步脚本标签)
- 然后它开始并行下载 script.js,因此在下载 script.js 时一切都会更进一步
- 然后浏览器正在执行 2 秒延迟的 JavaScript。同时 script.js 已下载。
- 也许“某些 HTML 行位于首屏”已经在 DOM 中,但这不是必需的。不管怎样,它还没有被渲染,因为屏幕上还没有什么可看的。
- Script.js 已下载,因此它开始执行 javascript。 Javascript的执行总是会阻塞渲染,所以现在“渲染”必须等待5秒。
因此,当动态创建脚本时,script.js 将被并行下载,但这并不一定意味着脚本不再阻塞渲染。他们可能会说 script.js 的(下载)加载不会阻止渲染,但他们不会这么说。
那他们怎么能说出这样的话呢?我不仅在这里看到它,还在其他谷歌官方文档中看到它。
现在人们可以阅读它并制作类似我的示例的内容(我只是将“执行时间”增大并延迟,以使其更加清晰)。然后人们会想:好极了! JavaScript 不会阻塞渲染,但实际上它是阻塞的,因此他们可以更好地在页面速度方面做出其他选择。