主要关于 WebKit 的渲染引擎内容
一、浏览器接收到 HTML 文件并转换为 DOM 树
DOM,全称Document Object Model文档对象模型
用户输入URL,三次握手,浏览器服务器建立连接后,浏览器请求对应的HTML文件。网络传输中的文件内容都是0/1组成的字节数据。
浏览器接收到HMTL文件后将字节数据转换为字符、字符串的形式(也就是程序员写的代码)。
在这之后,浏览器将字符串通过词法分析转换为Token()标记,(可以把token理解为符号标签,是代码的最小单位,依据HTML的标签将代码拆分便于浏览器编译理解),这一过程在词法分析中叫做标记化(tokenization)。
之后就是Token转换为node节点对象(html head link head...),最后节点对象根据联系构建为DOM树。
二、将 CSS 文件转换为 CSSOM 树
解析HTML文件过程中,浏览器会遇到CSS和JS文件,如“<link rel="xxx" href=""xxx>”,然后向服务器发送请求,得到·CSS文件,后面的的流程转换CSS到CSSOM树的过程和DOM树的过程相似。
(在写css样式时,注意层级扁平,避免写过于冗长的CSS选择器,因为浏览器会先从最年幼的标签往其年长的标签匹配, 过长回影响性能消耗资源)
三、生成渲染树
将DOM树与CSSOM树合并为渲染树。渲染树的任务就是匹配DOM和CSSOM的节点,并且捕获可见内容。即渲染树只会包括需要显示的节点和这些节点的样式信息,(比如 meta、 link标签就不会当做内容呈现出来,如果某个节点是display:none,也不会在渲染树中显示)
四、布局
浏览器渲染生成渲染树后,就会根据渲染树来进行布局,也可以叫做回流(reflow)。布局的意思就是获取渲染树的结构,节点位置和大小。(依据盒子模型来进行)
五、绘制
浏览器在布局好以后就安排页面的绘制,把渲染树以像素的形式绘制在页面,页面得以呈现
六、流程实例简版
以下为html解析过程中遇到js文件的情况,构建CSSOM后才能执行js文件,执行js文件会阻塞HTML解析过程。
浏览器在解析到 script
标签时,会暂停构建 DOM,完成后才会从暂停的地方重新开始。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script
标签放在 body
标签底部的原因。可以给 script
标签添加 defer
或者 async
属性。
当 script
标签加上 defer
属性以后,表示该 JS 文件会并行下载,但是会放到 HTML 解析完成后顺序执行,所以对于这种情况可以把 script
标签放在任意位置。
对于没有任何依赖的 JS 文件可以加上 async
属性,表示 JS 文件下载和解析不会阻塞渲染。
在js脚本加载和执行中,defer和async的区别:
defer 和 async 在网络读取(脚本下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
两者的差别:在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的。defer是立即下载但延迟执行,加载后续文档元素的过程将和脚本的加载并行进行(异步),但是脚本的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。async是立即下载并执行,加载和渲染后续文档元素的过程将和js脚本的加载与执行并行进行(异步)。
关于 defer,我们还要记住的是它是按照加载顺序执行脚本的
标记为async的脚本并不保证按照指定它们的先后顺序执行。对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行。
async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的。
以下为异步执行js文件(async)不会阻塞HTML解析
参考掘金《前端面试之道》和B站技术蛋老师的个人空间_哔哩哔哩_Bilibili
defer和async相关的点参考于大佬js中defer和async的区别_越努力,越幸运!-CSDN博客