浏览器渲染原理前言浏览器的主要功能可以用一句话来概括:将用户输入的URL转化为可视图像。从URL到DOM树;从DOM树到视觉图像;这两个过程之间的关系不是很清楚,我们可以把这两个过程统称为页面渲染;1、想一想网页的解析过程:一个网页从url输入到浏览器是经过了什么样的解析过程?要深入理解下载过程,首先要了解一个index.html下载后是如何解析并显示在浏览器上的;2.浏览器功能及组成2.1浏览器内核三叉戟(Trident):IE、360SafeBrowser、UC浏览器壁虎(Gecko):MozillaFirefoxPresto(PrestoMusic)->Blink(闪烁):OperaWebkit:Safari、360极速浏览器,搜狗高速浏览器,移动端浏览器(Android,iOS)Webkit->Blink:GoogleChrome,Edge浏览器的核心相当于汽车的引擎,是核心存在,它负责将代码转换成用户眼中的界面。我们常说的浏览器内核是指浏览器的布局引擎:layoutengine,又称浏览器引擎、页面渲染引擎或模板引擎;即一个网页下载下来后,我们的渲染引擎会帮我们分析;2.2进程和线程进程和线程的解释:进程:程序的一次执行,占有唯一的内存空间,是操作系统执行的基本单位;线程:进程内部独立的执行单元,是CPU调度的最小单位;browser:多进程、多线程模型Browser进程:浏览器的主进程,负责浏览器界面的显示和各个页面的管理;browsing是服务器中所有其他类型进程的祖先,负责其他进程的创建和销毁。它只有一个!Renderer进程:网页渲染进程,负责页面渲染,可以有多个渲染进程,不一定是打开的页面个数;GPUProcess:负责GPU相关;PluginProcess:负责控制一个网页使用的Plugin;3.浏览器渲染过程3.1渲染引擎解析过程渲染引擎拿到一个页面后,如何解析整个页面,最终呈现我们的网页呢?让我们通过下图更详细地了解它的过程;3.2渲染引擎主要模块渲染引擎主要包括:HTML解析器、CSS解析器、javascript引擎、布局模块、绘图模块;HTMLparser:解释HTML文档的解析器,其主要功能是将HTML文本解释成DOM树;CSS解析器:其作用是为DOM中的每个元素对象计算样式信息,为布局提供基础设施;Javascript引擎:使用Javascript代码可以修改网页的内容,以及css的信息。javascript引擎可以解释javascript代码,通过DOM接口和CSS树接口修改网页的内容和样式信息,从而改变渲染结果的布局:在DOM创建之后,Webkit需要结合元素具有相同样式信息的对象,计算它们的大小和位置等布局信息,形成一个能够表达所有信息的内部表示模型。网页的节点被绘制成图像结果4.渲染页面的详细过程浏览器渲染页面的全过程:浏览器会从上到下解析文档。4.1当HTML解析过程遇到HTML标签时,调用HTML解析器将其解析成相应的token(token是标签文本的序列化)并构建DOM树(即存储token并建立它们之间的关系)4.2生成CSS规则与style/link标签相遇调用解析器处理CSS标签并构建CSS样式树。4.3构建RenderTree当你有DOMTree和CSSOMTree时,你可以将两者结合起来构建RenderTree注1:link元素不会阻塞DOMTree的构建过程,但是会阻塞RenderTree的构建过程。这是因为在构建RenderTree时,需要相应的CSSOMTree;注2:RenderTree和DOMTree不是一对一的关系。比如display为none的元素,根本不会出现在rendertree中;4.4布局(layout)和绘制(Paint)第四步是在RenderTree上运行Layout,计算每个节点的几何形状。渲染树会指明显示哪些节点以及其他样式,但不会指明每个节点的大小、位置等信息;布局是确定渲染树中所有节点的宽高和位置信息;第五步是:将每个节点(Paint)绘制到屏幕上。在绘图阶段,浏览器将布局阶段计算的每一帧转换为屏幕上的实际像素;包括绘制元素的可见部分,如文本、颜色、边框、阴影,以及替换元素(如img)5.重绘和回流分析5.1重绘(Repaint)内容的第一次渲染称为绘画(paint),之后重新渲染称为重绘。重绘不会带来重新布局,因此不一定伴随着重新布局。浏览器根据元素的新属性重新绘制元素,使元素焕然一新。哪些属性会导致重绘?colorbackgroundbox-shadow..(比如修改背景颜色、文字颜色、边框颜色、样式等)5.2Reflow/回流(reflow)理解reflow回流:也可以叫回流,确定节点的大小和位置第一次,称为布局(layout),重新计算节点大小和位置修改称为回流。“重排/回流”必然导致“重绘”。而“重绘”,因为布局发生了变化,reflow是一件很耗性能的事情。哪些属性会导致回流?widthtopposition..(比如DOM结构发生了变化/布局发生了变化)5.3常见触发的“reflow/rearrangement”操作Reflow的成本远高于Repaint。因此,开发中尽量避免回流:修改样式时,尽量一次性修改,将多次更改样式属性的操作合并为一次操作,预先定义类,然后修改DOM的className避免频繁操作DOM。我们可以在一个DocumentFragment或者父元素中完成要操作的DOM操作,然后进行一次性操作;尽量避免通过getComputedStyle获取大小、位置等信息;对某些元素使用positionabsolute或fixed不会造成回流,但成本相对较高足够小,不会干扰其他元素。5.4合成和性能优化绘制过程可以将布局元素绘制成多个合成层。这是浏览器的一种优化方法。默认情况下,标准流中的内容绘制在同一层上。(Layer)中的一些特殊属性会创建一个新的复合层(CompositingLayer),新层可以使用GPU加速绘制。因为每个复合层都是单独渲染的,哪些属性可以组成一个新的复合层呢?一些常用属性:3Dtransformsvideo、canvas、iframeopacity动画过渡位置:fixedwill-change:一个实验性属性,提前告诉浏览器元素动画或过渡设置opacity可能发生什么变化,transform分层确实可以提高性能,但是它以内存管理为代价,因此不应将其过度用作Web性能优化策略的一部分5.5脚本元素与页面解析之间的关系我们现在知道了页面渲染过程,但是JavaScript在哪里?事实上,当浏览器在解析HTML的过程中遇到script元素时,是无法继续构建DOM树的;它会停止构建,先下载JavaScript代码,然后执行JavaScript脚本;会继续解析HTML,构建DOM树;为什么这样做?这是因为JavaScript的功能之一就是操作DOM,并且可以修改DOM;如果我们等到DOM树构建渲染完成后再执行JavaScript,会造成严重的回流和重绘,影响页面性能;所以遇到脚本元素时,先下载并执行JavaScript代码,再继续构建DOM树;但这也常常带来新的问题,尤其是在现代页面开发中:在当前的开发模式(如Vue、React)中,脚本往往比HTML页面更“重”,处理时间更长;因此,它会导致页面的解析被阻止。在脚本下载执行之前,用户在界面上看不到任何东西;为了解决这个问题,script元素为我们提供了两个属性:defer和async。6.defer和async属性6.1defer属性defer属性:告诉浏览器不要等待脚本下载,而是继续解析HTML并构建DOMTree。脚本会被浏览器下载,但不会阻塞DOMTree的构建过程;如果提前下载脚本,会等待DOMTree构建完成,在DOMContentLoaded事件之前执行defer中的代码;所以DOMContentLoaded会一直等待defer中的代码先执行。此外,多个带有defer的脚本可以按正确的顺序执行。从某种角度来说,defer可以提高页面的性能,建议放在head元素中;注意:defer只适用于外部脚本,脚本的默认内容会被忽略。6.2async属性sync属性有点类似于defer,同样可以防止脚本阻塞页面。async是让一个脚本完全独立:浏览器不会被async脚本阻塞(类似于defer);async脚本不能保证顺序,独立下载,独立运行,不会等待其他脚本;async不会保证在DOMContentLoaded之前或之后执行defer通常用于文档解析后需要操作DOM的JavaScript代码,对多个脚本文件有顺序要求;async通常用于独立脚本,不依赖于其他脚本甚至DOM;
