面试官:简单说下浏览器渲染页面的过程

716 阅读5分钟

前言

复习经典面试题

浏览器从获取HTML文件直到浏览器以像素点的方式在屏幕中绘制出页面的内容,这期间所经历的一系列步骤,叫做关键渲染路径(Critial Rendering Path)。

简单说下浏览器渲染页面的过程

1. 根据HTML结构构建DOM树

当我们打开一个网页后,浏览器会去向服务器请求对应的HTML文件,然而浏览器得到的是字节内容的HTML文件,于是浏览器将字节转换为字符,也就是我们写的HTML代码

image.png 但是这些代码我们看得懂,但是计算机看不懂,需要转换为计算机看得懂的语言,于是浏览器将字符转换为Token,可以将这里的Token理解为标签,例如将<div>转换为起始标签,将</div>转换为结束标签,这样字符就被Token化了,这样一来,计算机就能根据Token生成节点对象Node,将所有节点对象Node连在一起,就构成了一棵树,我们把它叫做DOM树

image.png

2. 构建CSSOM树

CSSOM是DOM结构上的样式的一种表示方式,浏览器在解析到<link>标签时,会根据href向服务器发送请求得到CSS文件,后面流程与DOM树的构建流程相似

image.png

3. 构建渲染树Render Tree

当构建完DOMCSSOM后,浏览器就会将这两棵树整合为渲染树Render Tree

image.png

4. 布局(回流)

当构建完渲染树后,浏览器就会根据渲染树进行布局

浏览器会获取渲染树的结构、节点位置和大小,根据盒子模型进行排列和嵌套

5. 渲染

渲染树的任务就是匹配DOM和CSSOM的节点,并且捕获可见内容,将捕获到的可见内容渲染到页面中

解析遇到linkscriptimg等标签会不会阻塞浏览器渲染

遇到link标签请求CSS文件的同时不会阻塞html解析,但会阻塞渲染,因为渲染树的构建需要DOM和CSSOM,两者缺一不可

遇到script标签时会停止构建DOM,因为JS可以操作DOM和CSSOM,因此浏览器需要构建完DOM和CSSOM再执行JS,否则会出现某些元素出现了又消失的情况,这也就是为什么要将script标签放在body标签底部的原因

请求JS文件时,实际操作中先得到CSS文件还是JS文件要看具体情况,但如果先得到并且解析完成JS文件也会发生阻塞,因为我们必须等到CSSOM构建完成后才能执行JS文件,因为渲染树要DOM和CSSOM构建完成后才能构建,而且JS是能操控CSS样式的。

不过在解析CSS文件并且构建CSSOM的时候,浏览器是可以下载并解析JS文件,等CSSOM构建完成后就可以执行JS文件了。

解析遇到display: none;会不会进入渲染流程

渲染树是最终能渲染到页面的元素的树形结构表示。也就是说,浏览器在解析时遇到display: none;的元素会放入DOM树,但不会进入渲染树

什么叫重绘?什么叫回流?

重绘 (repaint)

重绘是当元素只需要更改外观、风格,而不会影响布局的。比如更改background-color,就叫做重绘

回流 (reflow)

回流是当元素需要更改尺寸、布局时,需要重新构建渲染树的过程

区别

  • 回流一定会引发重绘,而重绘不一定会引发回流。比如只改变color就只会发生重绘而不会引起回流
  • 回流所需的开销比重绘多,渲染树上需要重新构建的节点越多,开销越大 也就是说重绘和回流在很大程度上影响了浏览器的性能

让文档脱离文档流有哪些方法?

  • float
  • absolute
  • fixed

减少重绘和回流,提高性能

作为开发人员,应该尽可能节省内存,优化浏览器性能,提高用户体验度,不要为了一时的刺激搞一些花里胡哨的动画(说的就是你:产品经理)。答应我,对浏览器好一些

1. 用visibility: hidden; 代替 display: none;

它们两者的区别是:visibility: hidden;是隐藏某个元素,但隐藏的元素仍需占用位置,会进入渲染树。而display: none;是让某个元素彻底消失,不占用原来的位置,并且不会进入渲染树。

也就是说在使用display: none;切换显示时,页面会产生回流,重新构建节点,对性能影响很大,而我们使用visibility: hidden;在切换显示的时候只会引起重绘而不会引起回流,对浏览器较为友好。

2. 少用或不用表格<table></table>

表格元素总是牵一发而动全身,可能一个很小的改动会造成整个表格的重新布局,开销很大

3. CSS选择器避免层级过多

.nav-bar div p span {
    font-size: 16px;
}

CSS的读取顺序为从右向左,也就是说:先找到所有的span,从第一个span开始沿着span的父元素查找p,如果中途找到了符合的节点就加入结果集,如果直到根元素html都没有符合条件的话,就从下一个span开始重复这个过程。如果层级过多则会增大浏览器的开销,所以应该尽量避免这种"套娃"的行为

推荐阅读

  1. 什么是回流,什么是重绘,有什么区别?
  2. CSS选择器从右向左的匹配规则
  3. 掘金小册-前端面试之道