chrome浏览器的渲染机制(为什么script脚本要放在文件末尾)

为什么script脚本要放在文件末尾?

原则:浏览器对script下载为非并行处理。

为什么浏览器要采用非并行的方式呢?其实很简单:

如果在html文件中我们有两个script引用,script1.js和script2.js,如果浏览器并行下载这两个文件,则可能会script.js先下载完成,则会立即执行script.js里面的函数,如果里面有一个函数是依赖于script1.js,而此时script1.js还没有下载完成,这时候此函数调用便会产生一个JavaScript error,为了避免这种情况,浏览器采用了严格按照html文件中定义的顺序下载script文件,并严格按照非并行方式下载的策略。

但是:有时候并不是所有的script文件都要放在最后:例如:button的点击事件如果需要js文件中的某个函数,如果这是我们的script文件都被放在了html文件最后的话,button这个element会在script下载完成之前被render出来,这时如果用户点击button就一定会出现一个script error;

解决方案:可以为所有js文件中需要被调用的函数在html中实现一个空函数(放在靠前的位置),这样当页面需要的js文件没有下载完成时,用户点击之后会触发一个空函数,避免了error,而等js文件加载完成之后这些function就会被override点击得到正确的响应。

浏览器的渲染机制:

1.DOMDocument Object Model,浏览器将HTML解析成树形的数据结构,简称DOM;

2.CSSOM:CSS Object Model,浏览器将css代码解析成属性的数据结构。

3.DOM 和 CSSOM都是以bytes->characters->tokens->nodes->object.model方式生成最终的数据。

DOM树的构建过程是一个深度遍历的过程,当前节点的所有子节点都够建好后才会去构建当前结点的下一个兄弟节点。

Rendeer Tree:DOM和CSSOM合并之后生成Render Tree

Render Tree 和DOM 一样,以多叉树的形式保存了每个节点的css属性,节点本身属性,以及节点的孩子节点。

浏览器的渲染过程:

1.浏览器请求到html代码后,在省城DOM的最开始阶段并行发起css,图片,js的请求,去轮他们是否在head里;

2.css文件下载完成,开始构建CSSOM

3.所有css文件下载完成,CSSOM构建完成后,和DOM一起生成render tree;

4.有了render tree,浏览器已经知道了网页有哪些节点,各个节点的css定义以及他们的从属关系。然后进行layout,也就是计算出每个节点在屏幕中的位置;

5.layout之后浏览器已经知道了哪些节点要显示,每个节点的css属性是什么,每个节点在屏幕中的位置是哪里,然后就进行painting,按照算出来的规则通过显卡把内容画到屏幕上;

前三步骤都可能在第一次painting之后又被更新多次,比如js修改DOM或者CSS属性;

layout和painting也会被重复执行,除了DOM CSSOM更新之外,图片下载完成后也会调用layout和painting更新网页;

当浏览器加载页面的时候首屏时间的DomContentLoad事件没有必然的先后关系;所有的css 尽早加载时间少首屏时间的最关键;js的下载和执行会阻塞DOM树的构建(中断DOM树的更新),所以script标签放在首屏范围内的html代码段里会影响首屏的内容;script标签放在body底部做与不做异步(async)或者延迟(defer)处理都不会影响首屏时间,但影响DOMContentLoad和load的时间,进而影响一来他们的代码的执行的开始时间。

总结:

如果script标签的位置不在首屏的范围内,不影响首屏时间,所有的script标签应该放在body底部是很有道理的;

从性能的角度考虑,即使在body底部的script标签也会拖慢首屏出来的速度,因为浏览器在最一开始就会请求它对应的js文件,而这,占用了有限的TCP连接数,甚至运行它所需要的CPU,这也是script标签会有async或defer属性的原因之一。


具体讲解(https://segmentfault.com/a/1190000004292479?utm_source=Weibo&utm_medium=shareLink&utm_campaign=socialShare)。

原文地址:https://www.cnblogs.com/Decmber/p/4750937.html