下面这样一段 html,在浏览器中打开,打上断点的效果如下面两张图所示,可见,js 的解析会终止 html 的渲染。
<html>
<body>
<div>1</div>
<script>
let div1 = document.getElementsByTagName('div')[0]
div1.innerText = 'time.geekbang'
</script>
<div>test</div>
</body>
</html>
而如果将这段 js 代码以 script 标签的形式插入的话,等加载到这里的时候就会引入网络进程来下载 js 代码,解析 html 文档也会被中断。
<html>
<body>
<div>1</div>
<script type="text/javascript" src='foo.js'></script>
<div>test</div>
</body>
</html>
另外,如果 JavaScript 文件中没有操作 DOM 相关代码,就可以将该 JavaScript 脚本设置为异步加载,通过 async 或 defer 来标记代码
async 和 defer 虽然都是异步的,不过还有一些差异,使用 async 标志的脚本文件一旦加载完成,会立即执行;而使用了 defer 标记的脚本文件,需要在 DOMContentLoaded 事件之前执行。
可见为了减少 js 的解析对 html 解析的影响,影响最小的应该是 defer,然后是 async。
可以看下这部分里有没有参考的内容 getbootstrap.com/docs/5.0/cu…
how browsers work 这篇文章又有一些查缺补漏的内容。
Speculative parsing Both WebKit and Firefox do this optimization. While executing scripts, another thread parses the rest of the document and finds out what other resources need to be loaded from the network and loads them. In this way, resources can be loaded on parallel connections and overall speed is improved. Note: the speculative parser only parses references to external resources like external scripts, style sheets and images: it doesn't modify the DOM tree–that is left to the main parser.
就是说遇到 script 标签之后,开始执行 js,但是同时还会使用另外一个线程解析剩余的 html,来下载 html 中其他的外部资源,这样的话就可以同步下载了。但是下载完之后不会修改 dom,而是继续等到解析到下载的内容位置再进行执行。
Style sheets Style sheets on the other hand have a different model. Conceptually it seems that since style sheets don't change the DOM tree, there is no reason to wait for them and stop the document parsing. There is an issue, though, of scripts asking for style information during the document parsing stage. If the style is not loaded and parsed yet, the script will get wrong answers and apparently this caused lots of problems. It seems to be an edge case but is quite common. Firefox blocks all scripts when there is a style sheet that is still being loaded and parsed. WebKit blocks scripts only when they try to access certain style properties that may be affected by unloaded style sheets.
因为 js 也可以获取和修改 style 的内容,所以 js 的执行一定要等到 style 文件下载完毕并且解析之后才开始。所以 css 也会阻塞 js。
进行 render tree 的生成过程中,就牵扯到 css 的多层问题,也就是在纵向上的布局,也就是说除了屏幕的二维位置,还需要考虑纵向上的三维位置,例如 position absolute 或者 float 元素。
而 render tree 是由 dom 和 cssom 共同生成的,所以过于复杂的 css 和无用的 css 会降低 render tree 的生成过程。