「一道面试题」输入URL到渲染全面梳理中-页面渲染篇


前置常识

此文是一道面试题,又不仅仅是一道面试题,不同的是这道题分了三篇文章来说,嗯。。可想而知

接上文,上文咱们讲了网络通信的部分,详细请看 「一道面试题」输入URL到烘托全面整理上-网络通信篇 ,那么该说说页面烘托的流程了,也便是当输入一个URL拿到T i [ V B了页面后,浏览器怎样解析,怎样出现

首要要了解这块内容,需求对下面这些常识Z r )点有一个简略认知

  • 线程/进程概念及1 t 9 Z &差异
  • 多线程/多进程概念
  • 浏览器的首要进W q ` r ( 8
  • 浏览器为什么是多进程
  • 烘托进程RendereU 0 n Er的首要线程
    • GUI烘托线程
    • JS引擎线程
    • 事情触发线程
    • 守时触发线程
    • 异步http恳求线程
  • 烘托进程的各个线程之间关系及合作

o # / t | 7 x [ *前写的一篇帖子 「硬核JS」一次b I ` x , P q e i搞懂JS运e 7 D转机制 – 传送门 里有介绍2 P ; H 2 j z Y $到,下面咱们仍是从头来一遍吧,花不了多长时刻,全当复习一遍,咱们也能够自行去看下来了解了解,当然假如你都清楚的话能够直接去看烘托进程

进程与线程

什么是进程

咱们都知道,CPU是核算机的核心,承担一切的核算使命

官方说法,进程CPU资源分配的最小单位

字面意思便是进行中的程序,我将它了解为一个能够独立运转且拥有自己的资源空间的使命程序

进程包括运转中的程序和程序所运用到x b = ( y x n A J的内存和系统资源

CPU 能够有许多进程,咱们的电脑每翻开一个软件就会发作一个或多个 进程 ,为什么电脑运转的软件多就会卡,[ 7 a $是因为 CPU 给每个 进程 分配资源空间,可是一个 CPU 总共就那么多资源,分出去越多,越卡,每个进程F % . : { 2间是相互独立的, CPU 在运转一个 进程 时,其他的进程处于非运转状况,CPU 运用 时刻片轮转调度算法 来实现一同运转多个进程

什么是线程

线程CPU 调度的最小单位

线程 是建立在 进程 的根底上的一次程序运转单位,通俗点解说 线程0 r 5 G h 6 Y 便是程序中的一个履行流,一个 进程 能够有多个 线程

一个 进程 中只要一个履行流称作 单线程 ,即程序履行时,所走的程序途径依照连续顺序排下来,前面的有必要处理好,后边的才会履行

一个 进程 中有多个履行流称作 多线程,即在一个程序中能够一同运转多个不同的 线程 来履行不同的使命, 也便是说答应单个程序创立多个并行履行的 线程 来完结各自的使命

进程和线程的差异

进程是操作系统分配资源的最小V b W a单位,线程是程序履行的最小单位` 1 t $

一个 进程 由一个或多个 线程 组成,线程 能够了解为是一个进程中代码的不同履行道路

进程 之间相互独立,但同一进程下的各个 线程 间同享程序的内存空间 (包括代码段、数据集、堆等) 及一些进程级. a 5 = K N 3的资源 (如翻开文件和信号)

调度和切换:线程上下文切换比进程上下文切换要快得多

多进程和多线程

多进程: 多进程指的是在同一个时刻里,同一个核算机系统中假如答应两个或两个以上的进程处于运转状况。多进程带来的好处是显着的,比方咱们能够在网易云听歌的一同翻开编辑器敲代码,编辑器和网易云的进程之间不会相互搅扰

多线程: 多线程是指程序中包括多个履行流,即在一个程序中能够一同运转多个不同的线程来履行不同的使命,也便是说答应单个程序创立多个` ; D并行履行的线程来完结各自的使命

JS为什么是单线程

JS的单线程,与它的用处有关,作为浏览器脚本语言,JavaScript的首要用处是与用户互动,以及操作DOM,这决定了它只能是单线程,不然会带来很杂乱的同步问题

比方,n 8 g A 8 U 4 h假定 JavaScript 一同有两个线程,一个线程在某个DOM节点上增加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准; 3 $

还有人说 js 还有 Worker 线程,对的,为了利用多核CPU的核算才能,HTML5提出Web Worker规范,答应 JavaScripR 9 )t 脚本创l X C立多个线程,可是子线程是完 全受主线程操控的,并且不得操作DOM

所以,这个规范并没有改动Jaw = i v ? ] % | CvaScript是单线程的实质

了解了进程和线程之后,接下来看看浏览s S D Y u /器解析,浏览器之间也是有少许差距的,不过大致是差不多的,下文咱们皆用市场占有份额最大的Chrome为例

浏览器相关

浏览器是多进程的

作为前端,免不了和浏览器打交道,浏览器是多进程的,拿 Chrome 来说,咱们每翻开一个Tab页就会发作一个进程,咱们运用 Chrome 翻开许多标签页不关,电脑会越来越卡,不说其他,首要就很耗CPU

浏览器包括哪些进程

  • Browser进程
    • 浏览w * , x ` P :器的主进程(担任和谐、主控),该进程只要一个
    • 担任浏览器界面显现,与用户交Q 6 { T u A Y互。如前进,后退等
    • 担任各个页面的办理,创立和毁掉其他进程
    • 将烘托(Renderer)进程得到的内存中的j ~ 1 | h ]Bitmap(位图),? s j M制作到用户界面上
    • 3 7 N J络资源的办理,下载等
  • 第三方插件进程
    • 每种类型的插件对应一个进程,当运用该插件时才创立
  • GPU进程
    • 该进程也只要一个,用于3D/动画制作等等
  • 烘托进程(重)
    • 即一* L % % L k s般所说的浏览器内核(Renderer进程,内部是多线程)
    • 每个[ $ 8 O 5 C m ?Tab页面都有一个烘托进程,互不影响
    • 首要作用为页面烘托,脚本履行,事情处理等

为什么浏览器要多进程

咱们假定浏览器是A f i @ i C { ) q单进程,那么某个TaL % Z j g f 4b页溃散了,就影响了整个浏览器,体会有多差

同理假如插件溃散了也会~ n j /影响整个浏览器

当然多进程还有其它的诸多优势,不过多论述

浏览器进程有许多,每个) c n Q 9G 5 q N程又有许多线程,都会占用内存

这也意味着内存等资源耗费会很大,有点拿空间换时刻的意思

到此可不仅仅为了让q k d咱们了解为E a w , k何Chrome运转时刻长s 9 A a q $ +了电脑会卡,哈哈,第一个要点来了

简述烘托进程Rendeu j 3 % O p } !rer(重0 o f ; ~ = l p)

页面的烘托,JS的履行,事情的循环,都在烘托进程内履行,所以咱们要要点了7 k 7 k Q , H解烘托进程

烘托进程是多线程的,咱们来看烘托进程的一些常用较为首要的线程

烘托进程Renderer的首要线程

GUI烘托线程
  • 担任烘托浏览器界面,解析HTML,CSS,@ K & T 7 F I L X构建DOM树和RenderObject树,布k 5 Z ( u 局和制@ g q , C W T作等
    • 解析h: @ [ U X 2tml代码(HTML代码实质是字符串)转化为浏览器认识的节点,生成DOM树,也D k { t便是DOM Tree
    • 解析css,生成CSSI B # Q = {OM(CSS规矩树)
    • 把DOM Tree 和CSSOM结合,生成Rendering_ N = Tree(烘托树)
  • 当咱们修正了一些元素的色彩或J c k y k / –许布景色,页面就会重绘(Repaint)
  • 当咱们修正元素的尺度,页面就会回流(ReB X u l _ ( x z Mflow: U o N 3 w 7 M)
  • 当页面需求Repaing和Reflow时GUI线程履行,制作页面
  • 回流(Reflow)比V # z c S重绘(Repaint)的成本要高,咱们要尽量防止Refl7 ` a p W 8 g 9ow和Repaint
  • GUI烘托线程与JS引擎线程是互斥的
    • 当JS引擎履行时GUI线程会被挂起(相当于被冻结了)
    • GUI更新会被保存在一个队列中比及JS引擎空闲时当即被履行
JS引擎F c 4线程
  • JS引擎线程便是JS内V , . 0 F D核,担任处理Javascript脚本程序(例如V8引擎)
  • JS引擎线程担任解析Javascript脚本,运转代码
  • JS引擎一向等候着使命队列中使命的到来,然后加以处理
    • X I { b a ^览器一同只能有一个JS引擎线程在运转JS程序,所以js是单线程运转的G h o Y j ?
    • 一个Tab页{ ) O B Q i 0 v x(renderer进程)中无论什么时分都只要一个JS线程在运转JS程序
  • GUI烘托线程与JS引擎线程是互斥的,js引擎线程会堵塞GUI烘托线程
    • 便是咱们常遇到的JS履行时刻过长,构成页面的} B n a N @ C烘托不连贯,导致页面L s – D j l 2 I I烘托加载堵塞(便是加载慢)
    • 例如浏览器烘托的时分遇到“标签,就会中止GUI的烘托,然后js引擎线程开端作业,履行8 w n # K { w里边的js代码,等js履行完毕,js引擎线程中止作业,GUI持续烘托下面的内容。所以假如js履行时刻太长就会构成页面卡顿的状况
事情触发线程
  • 归于浏览器而不是JS引擎c ^ &,用来操控事情循环,并且办理着一个事情队列(task queue)
  • 当js履行碰到事情绑定和一些异步R V ~ ^ 2 f k t操作(如setTimeOut,也可来自浏览器内核B i w的其他线程,如鼠标点击、AJAX异步恳求等),会走事情触发线程将对应的事d N m x = 1 6 }情增加到对应的线程中(比方守时器操作,便把守时器t i 5 p } 3事情增加w 6 v ( N h }到守时器线程),等异步事情有了结果,便把他a s }们的回调操作增加到事情队列,等候js引擎线程空闲时来处理。
  • 当对应的事情符合触发条件被触发时,该线程会把事情增加到待处理队列的队尾,等候JS引擎的处理
  • 因为JS是单线程,所以这些待处理队列中的事情都得排队等候JS引擎处理
守时触发器线程
  • setIntervalsetTimeout 所在线程
  • 浏览器守时计数器并不是由JavaScript引擎计数的 (~ e b . J = –因为JavaScript引擎是单线程的,假如处于堵塞线程状况就会影响记计时的精确)
  • 经过独自线程来计时并触发守时(计时完毕后,增8 l ; Z b $ o加到事情触发线程的事情队列中,等候JS引擎空闲后履行),这个线程便是守时触发器线程,也叫守时器线程
  • W3C在HTML规范中规矩,规矩要求setTimeB 2 M - R m 0out中低于4ms的时刻间隔算为4ms
异步http恳求线程
  • 在XMLHttpRequest在衔接后是经过浏览器新开一个线程恳求
  • 将检测到状况变更时,假如设置有e 0 8 }回调函数,异步线程就发– S ,作状况变更事情,将这个回调再放入事情队列中再由JavaScript引擎履行
  • 简略说便是当履行到一个http{ { ( 3 G _ X @异步恳求时,就把异步恳求事情增加到异步恳求线程,等收到呼应 (精确来说应该是http状况改动),再把回调函数增加到事情队列,等候js引擎线程来履行

了解了上面这些根底后,接下来咱们开端进入今日的正题,输P H z入URL拿到资源之后,怎样烘托,又经历了那些进程?

烘托进程

Webkit烘托流程图

咱们都知道,浏览器之间的烘托流程是有些细微差别的,咱们这儿介绍的一些常识 1 z点是基于Chrome的,也便是Webkit,毕竟它是主流,先来看一下Webkit的烘托流程图

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

咱们假如第一次看到这张图,或许会有点迷茫,不知从哪看起,别急,先大致过一眼,咱们下h e Z @ c面会慢慢介绍,一步步的剖析,假如咱们完好的阅读完此文,无妨回过头来再看一遍这张图,| B L 2 . 9 v R (会清晰许多

解析HTML构建DOM树

浏览器烘托,那么浏览器必定就拿到页面内容了,必定要先解析HTML的

话不多说,咱们直接来看HTML解析的图 ( 网图侵删 )

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

假如是; ( s S ) m _ ] [第一次看到这~ O R 2 / ; Q张图或许看不懂,不要紧,慢慢道来

先来看图中解析DOM的这几个大进程

Bytes(字节) -> Characters(y T x 6 B字符) -> Tokens(词) -> Nodes(节点) -> DOM(DOM树)

首要,建议恳求拿到页面 HTML 内容,r z D这个内容它是0/1这样的原始 字节约

接着,浏览器拿到这些 HTML 的原始字节,依据文件的指定编码 (例如 UTF-8) 将它们转换成各个) a ] t t G 2 N – 字符

现在字节约变成了 字符流 ,也便是一大c 4 6 s串字7 E /符串

为了把 } 8 k W L E B u符流 解析成正确的 DOM 结构,浏览器还要持续努力

接着进行 词法解析 ,把字符流初步解析成咱们可了解的 ,学名叫 token

嗯?什么是词 (Token)?

是编译原理中的最小单元,如标签开端、特点、标签完毕、注释、CD6 i : T s sATA节点

Token 会标识出当时 Token 的种类,有点绕,怎样说便利了解呢,举个比如

<divG _ ? ] t t 9 S class="hahaA W . K E">haha</div>

如上,l { 3 a这是一个标签它有一个cla= I h (ss特点 (废话),可是浏览器拿到的仅仅字符串,它不知道这都是什么标签有啥特点要做什么,那么得给它一点一点拆开读,便是词法解析,怎样解析,就像下面这样

1. <R Z G * ! u ~;div					# 哦,看到了&lI 1 Y 8 ; , c g Vt;div,这是一个di] L F i f g s qv标签的开端
2. class="haha" # 这是一个class特点
3F ? : z. >						# 哦,到这儿是一个完好h l F [的div开端标签
4. haha					# 嗯,这是一个文本
5. </dz , L u Piv>				# 奥,看到了</div>,整个div标签完毕了

词法解析 是编译原理中的概念,上面是极度简化版本 (防大佬死磕),仅仅为了便利咱们了解

现在了解了吗,Tokens 这个阶段中会标识出当时 Token开端标签 或是 完毕标签 亦或是 文本 等信息

那么咱们收回思路,接着上面的进程,经历 词法解析 咱们把字符流解析成了 词 (Token)

接着在每个 Token 被生成后,会立刻耗费这个 Token 创立出节点目标,K 0 K 2 $ ! G 0 8便是 节点 (Nodes) 阶段

把开端完毕标签配对、特点赋值好、父子关系这些都衔接好了,W Q ^ * N终究就构成了 DOM

后边a x A }这两小步也可称为 语法解析 ,到此 DOM Tree 就解析完了

另外多嘴一句,DOM树(DOM Tre_ Q E O Ke) | 文档目标模型 ,这些东西说的都是 DOM树

解析H : E [ / c o )CSS构建CSSOM树

HTML 解析,那必定有 CSS 解析,比方咱们构建 DOM 的时分遇到了 link 符号,该B o 符号引证一个外部 CSS 款式表,那么浏览器会认o A r为它需求这个外部款式资源,就会当即宣布对该资源的恳求,并返回款式内容,也i % p [ V ` 8 ) r是字节约

与处理 HTML 时相同,将收到的 CSS 规矩转换成某种浏览器能够了解和处理的东西,根本进程重复 HTML 进程,不q 5 C o B { d R过是构建 CSS 而不是 HTML

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

CSS 字节转换成字符,接着词法解析与法解析,终究构成 CSS目标模型F q 0 -(Cr V B h L q v {SSOM) 的树结构

咱们都知道,节点款式是能够承继的,所以在构建的进程中浏览器得递归 DOM 树来确定元素究竟是什么款式,为了 CSSOM 的完好性,只要等构建完毕才干进入到下一个阶段,所以就算 DOM 现已构建完了,也得等 CSSOQ L + g 7 L . 5 QM,然后才干进入下一个阶段

所以 CSS1 ^ : 0 的加载速度与构建 CSSOM 的速度会影响首屏烘托速度,这便是咱们常说的 CSS 资源T C :的加载会堵塞烘托

怎样优化?DOM树要小,CSS尽量用 idclass 少直接用标签

解析JavaSc_ z k . [ $ 8 ) !ript脚本

这个解析 JS 的进程是不固定的,因为r | O G U I ?在构建DOM 树的进程中,当 HTML 解析器遇J 1 =到一个 script 符号时,即遇到了js,当即堵塞DOMa ; c H w m _ 7树的v C m 构建,就会将操控权移交给 JavaScript 引擎,比及 JavaScript 引擎运转完毕,浏览器才会从中止的( % c ] . b当地恢复DOM树的构建

为什么上面也说了,JS会对DOM节 Q [ ~ % I U点进行操作,浏览器无法猜测未来的DOM节点的具体内容,为了防止无效b 0 x A 6操作,节约资源,只能堵塞DOM树的构建

例如,若不堵塞DOM树的构建,若 JS 删除了某个DOM节点A,那么浏览器为构建此节点A花费的资源便是无效的

若在 HTML 头部加载 JS 文件,因为 JS 堵塞,会推迟页面的_ ~ /首绘,所以为了加速页面烘托,一般将 JS 文件放到HTML 底部进行加载,或是对 JS 文件履行 asyncdefer 加载

  • async 是异步履行,异步下载完毕后就会履行,不保证履行顺序,一定在 onload 前,但不确定在 DOMContentLoaded 事情的前或后
  • defer 是推迟履行,在浏览器看起来的作用像是将脚本放在了 body 后边相同(尽管按规范应该是在 DOMContentLoaded 事情前,但实际上不同浏览器的优化作用不相同 b |,也有或许| x p S ; j 4 [ D在它后边)

构建烘托树/出现树(Render Tree)

烘托树 ( Renp P jder Tree ) 由 DOM树CSSOM树 兼并而成,但并不是有必要等 DOM树CSSOM树 加载完结后才开端兼并构建 烘托树,三者R l (的构建并无先后条件,也并非完全独立,而是会有交叉,并行构建,5 / 2 _ B = b 8 2因此会构成一边加载,一边解析,一边烘托的作业现象

CS_ 3 / 7 8 ( n c VSOM 树DOM 树 兼并成烘托树,烘托树 只包括烘托网页所需的节点,然后用于核算每个可见元素的布局,并输出给制作流程,将像素烘托到屏幕上

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

如上图 ( 网图侵删 ) ,为了构建烘托树,咱们看看浏览器都做了什么

  • 浏览器首要会从DOM树的根节点开端遍历每个可见节点
    • 例如脚本符号、元符号等有些节点不行见,因为它们不会体现在烘托输出中,所以会被疏忽
    • 某些节点经过 CSS 躲藏,因此在L 3 |烘托树中也会被疏忽* – 5 ! 2 L,例如上图的其间一个 s. D ( / f : , = =pan 标签有d , ! f ( K D ( display: nonh 7 Ze 特点,也会被疏忽
  • 关于每个可见节点,找到其对应的的 CSSOM 规矩并运用它们
  • 输出可见节点,连同其内容和核算的款式

布局(Layout)

烘托树 一同Y 6 a ^ i包括了屏幕上的一切可见内容及其款式信息,有了烘托树,再接着就要进入布局 ( layout ) 阶段A I @ )了,到目前为止,咱们核算Z ( a U ] ? R } D了哪g c F ` Y 4 W些节点应该是可见的以及它们的核算款式,但咱们还没有核算它们在? # P设备 视口 内的确切方位和巨细,这便是 布局 ( Layout ) 阶段,也称为 主动重排回流 ( Reflow )

此阶段一般意味着元素的内容、结构、方位或尺度发作了改动,需求从头核算款式+ 8 N % 6和烘托树

简略举个比如,咱们看下面这段代码

<!DOCTYPE html>
<D j Q k v 2 1 y;html>
<head>
<meta name="view1 s 0port" conl z T 3 _ P # {tent="width=device-width,iD ~ C E t n ( Bnitial-scale=1">
<title>hahaha</title>
</head>
<body>
<div style="width: 50%">
<div style="width: 50%">Hello world</div>
</div>
</body>
</htmx 1 C }l>

上面代码网页的正文包括两个嵌套p 0 U # B [ div:第一个父 diE h o b u Pv 将节点的显现尺度设置为视口宽度的 50%,父 div 包括的第二个 div 将其宽度设置为其父项的 50%,即视口宽度的 25% (网图侵删)

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

布局流程的输出是一个 盒模型,它会精确地捕获每个元素在视口内的确切方位和尺度,当然,一切相对测量值都转换为屏幕上的肯定像素

咱们先往下看,稍后还会给咱们介绍

制作(Painting)

经历了以上种种进程,终于来到了 制作- b ~ ,这一步听名字k 4 n Q就能想t 3 M ) + / Z v g到其作用了

经由$ – ?前几步咱们知道了哪些节点可见、它们的核算款式以及几许信息,咱们将这些信息传递给终究一个阶段将烘托树中的每个节点转换成屏幕上的实际像素,也便是俗称的 制作栅格化

制作 进程中有一种制作叫 重绘,也便是下咱们要说的

重绘(Repaint)

元素发作的改动仅仅影响了元素的一些外观之类的时分(例如,布景色,边框色彩,文字色彩等),此刻只需求运用v 4 w w新款式制作这个元素就能够了,这叫S C u ~ + ; A重绘 ( Repaint )

回流 (Reflow)

上面咱们现已说过了 回流 ,当然B $ y A 0 N * Q也叫 重排 ,要知道,回流 一定伴随着 重绘重绘 却能够独自出现,比照来看,明显回流的成本开支要高于N 9 { 0 X # & { %重绘,并且一个节6 2 ,点的回流往往还会导致子节点以及同级节点的回流,所以优化方案中一般都包括,尽量防止 回流

什么会引 P =起回流

  • 页面烘托初始化

  • DOM结构改动,比方删除了某个节点

  • render树改动,比方削减了padding

  • 窗口 resize* A & u Y ; 4 c

  • 某些 JS 特点,| t i ; | d 7引发回 p ( ) r流,许多浏览器会对回流做优化,比及数量满足时做一次批= 0 $ # c D a处理回流,
    但除了 render树 的直接改动: ; a,当获取一些特点时,浏览器为了获得正确的值也会触发回流,这样Z r ` n c L L 4使得浏览器优化无效

  • offset ( Top/Left/Width/Height )

    • scroll ( Top/Left/Width/Height )
    • cile$ Z B w E 9 dnt ( Top/Left/Width/Height )
    • width, height
    • 调用了 getComputedStyle() 或许IO r S 9 WE的 currentStyle

怎样削减和防A I F S T L z a E止回流重绘

上面咱们提到,回流开支太大了,那么咱们必定是要优化的,接着看,其实便是尽量防止上面那些操作

  • 削减逐项更改款式,最好一次性更改 st8 6 X I E s Jyle,或许N 9 – G G将款式界说为 class 并一次性更新
  • 防止循环操作DOM,让DOM离线后再修正
    • 创立一个 documentFragment ,在它上面运用一切DOM操作,终I 1 M + [ / ]究再把它增加到 window.document
    • 先把DOM节点 display:none ( 会触发一次 reflow),然后做修正后,再把它显现出来
    • 克隆一个DOM节点在内存里,修正之后,与在线的节点相替换
  • 防止屡次读取offset等特点,无法防止则将它们缓存到变量
  • 将杂乱的元素肯定定位或固定定位,使得它脱离文档流,不然回流代价会很高
  • 改动字体巨细也会引发回流,所以尽或许削减这种操作
  • table布局,一个小改动会构成整个table的从头布局,所以,少用为好

总归,说来说去,回流重绘,特别是回流,特别耗费资源,尽量防止就好,关于一些CSS特点会引起的回流重绘,能够去这个网站查检查 csstriggers.com/

组成(Composite)

终于来到了终究一个点 组成 ,咱们先来总结一下上面的进程,到目) ? Y E # 3 Y前咱们经历烘托进程如下

  • 首要解析 HTML 文档,构成 DOM 树
  • 接着解析 CSS,发作 CSSOM树
  • 在DOM和CSSOM树解析进程中,遇到 JS,会当即堵塞DOM树的构建,JS解析完结,接着走上面两步
  • 再接w _ q N着,浏览器! 4 ? f经过DOM和CSm S e ` N N E t WSOM树构建烘托树 ( Render树 )
    • 这个进程中,DOM中不行见标签元素不会放到烘托树中,就像<head></head> 或 display:none
    • CSSOM树规矩会附加给烘托树的每个元素上
  • 烘托树构建完结,浏览器会对这些元素进行定位和布局,这一步也叫 重排/回流 ( Reflow) 或 布局(Layout )
  • 接下来制作这些元素的款式,色彩,布景,巨细及边框等,这一步也叫做 重绘 (Repaint)
  • 再接下来是咱们这终究一步组成( composite ),浏览器会将各层信息发送给GPU,GPU将各层组成,显现在屏幕上

关于组成这一进程,预备细聊一会儿,让咱们对其有个根本概念,因为刚开端疏忽了它

首要,咱们需求简t – ` u p C N 6略了解一些根本概念

浏览器烘托方法

浏览器在烘托图形的时分,有一个绘图上下文,绘图上下文又分红两种类型

  • 第一种是用来制作2D图形的上下文,称之为2D绘图上下文(GraphicsContext)
  • 第二种是制作3D图形的上下文,称之为3D绘图上下文(GraphicsContext3D)

网页也有三种烘托方法

  • 软件烘托(CPU内存)
  • 运用软件绘图的组成化烘托(GPU内存)CSS3D、WebGL
  • 硬件加速的组成化烘托(GPU内存)

当然,这些咱们也不需求深化了解,知道它们的存在即可

软件烘托技能

Webkit 在不需求硬件加速内容的时分(包括但不限于 CSS3 3D变C X RCSSr l P D3 3D变换WebGL视频),它就能够运用 软件烘托技能 来完结页面制作

上面咱们看到了软件烘托技能,它是什么呢?咱们接着看

关于每个烘托目标,需求三个阶段制作自己

  • 第一阶段是制作该层中一切块的布景和边框
  • 第二阶段是制作起浮内容
  • 第三阶段是远景 ( Foreground ) ,也便是内容部分、轮廓、字体色彩、巨细等 ( 内嵌元素的布景、边框等发作在这一阶段 )

硬件加e X : j ; i速技能

硬件加速技能是指运用 GPU 的Y @ * Y * ( S 1硬件才能来协助烘托网页 ( GPU的作用首要是用来制作3D图形并且功能很 nice )

一般图层和复合图层

t c U K览器烘托的图层一般包括两大类B 1 v R一般图层 以及 复合图层

一般文档流咱们就能够了解为一个复合图层,咱们叫它默许复合层,因为里边不论增加多少元素,其实都是在同一个复合图5 R q Z k层中,absolute 布局、 fixed 也相同,尽管能够脱离一般文档流,但它仍然归于 默许复合层

复合图层,能够独立于一般文档流中,改动后能够防止整个页面重绘,提高功能,但也不要大量运用复合图层,不然因为资源y K 7 ) 0 H – b l耗费过度,页面反而会F Q & V X h变的更卡,因小失大

GPU中,各个复合图层是独y e A W q 8 N ] )自制作的,所以也互不影响,经过 硬件加速 的方法,会声明一个 新的复合图层 ,它会独7 ; B d o e N .自分配资源,当然也会脱离一般文档流,这样一来,不论这个复合图层中怎样改动,也不会影响 默许复合层 里的回流重绘

何为复合图层/硬件加速

复合图层或许说硬件加速,其实便是O ] $ e = d s仅触发组成 composite ,那么也就有必要符合以下三个条件

  • 不影响文档流
  • 不依靠文档流
  • 不会构成重绘

寻思一下,能够做到这种状况得还真的不多 ( Chrome )

  • 最常用的方法是 transform
  • opacity 特点 / 过渡动画 (需求动画履行的进程中才会创立组成层,动画没有开端或完毕后元素还会回到之前的状况)
  • will-chang 特点 (这个比较偏远),一般合作 opacitytranslate 运用,除了上述能够引发硬件加速的特点外,其它特点并不会变成复合层,作e P /用是提前告诉浏览器0 [ Z M V n ?要改动,这样浏览器会开端做一些优化作业 (最好用完后就开释)
  • <canvas> <webgl> 等元素
  • 还有曾经的 flash 插件等等

通俗一点,假如咱们给一个元素加了 tranp Ssform 特点吧,那么该元素就不会影响也不会依靠文档流,也不会构成重绘,就变成了一个复合图层,也就能够说咱们对它运用了传说中的 硬件加速技能

absolute?

到了这儿,咱们或许有些迷惑,咱们不是常说 absolute 是脱离文档流吗,为什么上面复合图层或许说硬件加速中没有 absolute

其实,absolute 尽管能够脱离一般文档流,可是无法脱离默许复合层,就像它的 left 特点能够运用百分比的值,依靠于它的; ? I W offset parent

所以,就算 absolute 中信息改动时不会改动一般文档流中的 烘托树 ,但浏览器终究制作时,是整个复合层制作的,所以 absolute 中信息改动,仍会影响整个复合层的制作,浏览器仍是会重w ~ G @ G绘它,假如复合层中内容多,absolute 带来的制作信息F { q % L改动过大,资源耗费也非常严峻

而咱们上面说的硬件加速,那直接便是在另一个复合层了,( i 4 ( j所以它的信息9 t C t改动不会影响默许复合层,当然内部必定会影响归于自己的复合层,仅仅是引发终究的组成烘托

页面烘托优化

浏览器对上文介绍的关键烘托进程进行了许多优化,针对每一次改动发作尽量少的操作,还有优化判断从头制作或布局的方法等等,据上文所述,总结下页面烘托这块的优化实践,不分先2 ` k后,咱们也可一块来弥补

  • HTML文档结构层次尽量少,最好不深于六层

  • JB o – – W ~S 脚本尽量后放

  • 款式结构层次尽量简略

  • 少数首屏款式运用内联方法放在标签内

  • 在脚本中尽量削减DOM操作S q U 1,尽量访问离线DOM款式信息,防止过度触发回流

  • 削减经过 JS 代码修正元素F & b 款式,尽量运用修正 class 名方法操作款式或动画

  • 尽量削减浏览器重排和重绘的一些状况发作

  • 2020年了!就不要运用 table b t N $ $ l 布局了

  • CSS 动画中尽量只运用 transformopacity` C V | ) / V ,不会发作重排和重绘

  • 躲藏在屏幕外,或在页面翻滚时,尽量中止动画

  • 尽或许只运用 CSS 做动画,CSS动画必定( f Z比 JS 动画要好许多

  • 防止浏览器的隐式组成

  • 改动复合层的尺度

终究

上面讲的有些随意,终究再来波官方点的总结吧

建议一个恳求,咱们拿到了页面,下载完的网页将被交给浏览器内核(烘托进程)进行处理

  • E . T . :要,依据顶部界说n 7 y ] g的DTD类型进行对应的解析方法
  • 烘托进程内部是多线程的,网页的解析将会被交给3 Z ] ? N $内部的GUI烘托线程处理
  • 烘托线程中的HTML解说器,将HTML网页和资源从字节约解说转换H M e O成字符流
  • 再经过词法剖析器将字符流解说成词
  • 之后经过语法剖析器依据词构建成节点,终究经过这些节点组成一个DOM树
  • 这个进程中,假如遇到的DOM节点是 JS 代码,就会调用 JS引擎 对 JS代码进行解说履行,此刻由 JS引擎GUI烘托线程 的互斥,GUI烘托线程 就会被挂起,烘托进程中止,假如 JS 代码的运转中对DOM树进行了修正,那么DOM的构建需求从新开端
  • 假如节点需求依靠其他资源,图片/CSS等等,就会调用网络模块的资源. u 3 6 [ 加载器来加载D m K [ b | 2 u它们,它们是异步的,不会堵塞当时DOM树的构建
  • 假如遇到的是 JS 资源URL(没有符号异步),则需求中止当时DOM的构建,直到 JS 的资源加载并被 JS引擎 履行后才持续构建DOM
  • 关于CSS,CSS解说器会将CSS文件解说成内部表示结构,生成CSS规矩树
  • 然后兼并CSS规矩树和DOM树,生成 Render烘托树,也叫T a b B出现树
  • 终究对 Render树进行布局和制作,并将结果经过IO线程传递给浏览器操控进程进行显现

页面烘托t o @篇到此就完毕了,又是上万字,好像也没讲太多东西,咱们仍是只能以庞观的n o L D W方法去了解,私下想深化的话仍是要多看些相关材料,此文也是我看了许多材料输出的,看完本文,再去看材料或深化应该也会简单了解一些吧,这几篇帖子的核心都脱离不了那道经典面试题,那么看到了这儿根本的一些常识点都现已给咱们论述过了,能够自己测验总结一番了,一定要自己总结再看下文总结篇,这样咱们也算没白浪费时刻

下一文「一道面试题」输入URL到烘托全面整理下-总结篇,待续哦。。

对您有协助的话,动动小手,点个赞鼓励下吧,当然,个人了解,如有不正,欢迎指出,不胜感激

哦,还有,能够加个好友加下群一同交流噻,大众号【不正经的前端】也欢迎关注呦

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

参阅 ( 参阅了许多文章,贴了三个认为比较好的,引荐咱们看一看 )

  1. 从输入URL到页j l W面加载的进程?怎样由一道题完善自己的前端常识系统

  2. 从浏览器多进程到JS单线程( – v ? * L,JSg R z I I } 5 : C运转机制1 N ^ p / H * m :最全面的一次整理

  3. 一篇文章说清浏览器解析和CSS(GPU)动画优化

发表评论

提供最优质的资源集合

立即查看 了解详情