总览代码在我们的浏览器中是怎么工作的

前言

作为前端工程师,浏览器几乎是我们成家立命不可或缺的重要工具,然而现在我们前端路线的学习往往会忽视这一块,很多人学完前端基础三件套就去开始搞jquery或者现在如火如荼的Vue或者React,很大程度上浏览器对于这个学习路线制作到了能使用,能展示你做的东西,仅此而已。

但是我们要知道的是,尽管我们不是浏览器开发者,我们仍然需要充足的浏览器知识,尽管原生与小程序如火如荼,H5仍然是我们赖以生存的根本,而区别前端工程师与会写前端的人的重要标准之一,就是怎么利用好浏览器带给用户最好的体验。

纵览

首先我们要知道浏览器是干嘛的,简单的说它就是把我们访问的URI渲染成一个用户友好的界面,winter叔在重学前端课中讲到一个很清晰的图,来概括这个过程:
总览代码在我们的浏览器中是怎么工作的
关于HTTP,我已经讲了很多了,其实这里还包括dns解析之类的,我们暂时不去考虑,下面从DOM树的构建开始。

DOM

这一段要是想讲明白需要很多科班知识 ,诸如编译原理,状态机,词法分析之类的,说实话我自己看也是迷迷糊糊的,这里就简单的概括一下:

  1. 第一步我们得到了响应体中的html文件,利用状态机去对html文件进行分词处理。
  2. 第二部我们使用栈结构把分好的词变成DOM树结构。

对,就这么简单,但是内里涉及到的知识是十分庞大的,你想看具体实现的话可以去看 winter叔的课。

计算CSS

看完上一段,你可能意识到了一些问题,CSS去哪儿了?

这就涉及到了第三步,浏览器是如何把CSS规则应用到节点上,并给这棵朴素的DOM树添加上CSS属性的。

首先CSS选择器这个名称,可能会给你带来一定的误解,觉得好像CSS规则是DOM树构建好了以后,再进行选择并给它添加样式的。实际上,这个过程并不是这样的。

因为浏览器处理上面过程是一种流水线作业,它不会说等全部DOM结构构建完毕才去给DOM树挨个添加样式,同样也是使用流式结构进行的。

同样,CSS需要先经过词法分析和语法分析,变成计算机能够理解的结构,其中也会牵扯到很多编译原理的内容,之后我们拿到了编译好的CSS语法树,接着根据CSS规则应用到DOM树上,为DOM结构添加显示相关属性。

排版

这一步骤和前面两点有些不同的主要原因是前面我们都是一个元素一个元素的产出,但是对于排版来说我们显然不可能一个元素一个元素的来,因为不同元素之间很可能是有着错综复杂的联系的。

浏览器最基本的排版方案是正常流排版,它包含了顺次排布和折行等规则,这是一个跟我们提到的印刷排版类似的排版方案,也跟我们平时书写文字的方式一致,所以我们把它叫做正常流。

浏览器的文字排版遵循公认的文字排版规范, 同时,浏览器又可以支持元素和文字的混排,元素被定义为占据长方形的区域,还允许边框、边距和留白,这个就是所谓的盒模型。

在正常流的基础上,浏览器还支持两类元素:绝对定位元素和浮动元素,绝对定位元素把自身从正常流抽出,直接由top和left等属性确定自身的位置,不参加排版计算,也不影响其它元素。绝对定位元素由position属性控制;浮动元素则是使得自己在正常流的位置向左或者向右移动到边界,并且占据一块排版空间。浮动元素由float属性控制。

如今很火的flex和 grid排版方式则是独立于正常流之外的排版方式。

首先我们看正常流,在正常流的文字排版中,多数元素被当作长方形盒来排版,而只有display为inline的元素,是被拆成文本来排版的,会被直接排入文字流中, display不为inline的元素或者伪元素,会以盒的形式跟文字一起排版。

float排版大家应该很熟悉了,block元素不指定width的话,默认是100%,一旦让该div浮动起来,立刻会像inline元素一样产生包裹性,宽度会跟随内容自适应,不熟悉的话推荐大家看这篇文章

关于absolute其实有很多和float类似的地方,我这里就不展开了,推荐这个博主的文章

渲染合成和绘制

关于最后的位图操作部分,这包括了渲染、合成和绘制三个方面。渲染过程把元素变成位图,合成把一部分位图变成合成层,最终的绘制过程把合成层显示到屏幕上。当绘制完成时,就完成了浏览器的最终任务,把一个URL最后变成了一个可以看的网页图像。