2024年Web前端最新字节面试题:详解浏览器工作原理,大厂直通车

最后

编程基础的初级开发者,计算机科学专业的学生,以及平时没怎么利用过数据结构与算法的开发人员希望复习这些概念为下次技术面试做准备。或者想学习一些计算机科学的基本概念,以优化代码,提高编程技能。这份笔记都是可以作为参考的。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

名不虚传!字节技术官甩出的"保姆级"数据结构与算法笔记太香了


上图展示的是webkit的主要工作流程,接下来我们按照图片的流程来逐渐阐述Webkit是如何工作的。但在这之前我们先要明白从HTTP请求回来开始,呈现引擎的整个工作流程不是一步做完再做下一步,而是一条流水线。

从HTTP请求回来,就产生了流式的数据,后续的DOM树构建、CSS计算、渲染、合成、绘制,都是尽可能地流式处理前一步的产出:即不需要等到上一步骤完全结束,就开始处理上一步的输出,这样我们在浏览网页时,才会看到逐步出现的页面。

HTML解析:从HTML到DOM树

Webkit会用HTML解析算法将HTML转换成DOM树。下面让我们看一下HTML到DOM树的转换:

接下来让我们了解一下HTML解析算法,HTML解析算法的流程如下图所示:

它分为标记化和树构建两个过程:

标记化:

将输入的内容解析成多个标记(HTML标记包括起始标记,结束标记,属性名称,属性值)。标记生成器识别标记,传递给树构造器,然后接受下一个字符以识别下一个标记;如此反复直至结束。标记化算法是通过状态机实现的。

树构建:

标记生成器发送的每个节点都由树构建器进行处理,规范中定义了每个标记所对应的DOM元素,这些元素会在接收到对应的标记时构建,这些元素不仅会被添加到DOM树,还会添加到开放元素的堆栈中。此堆栈用于纠正嵌套错误和处理未关闭的标记,其算法也可以用状态机来表示。

HTML解析完成后,浏览器会将文档状态标注为交互状态,并开始解析那些处于deferred模式的脚本,然后文档状态设置为完成,一个加载时间将随之触发。

CSS解析:从CSS到StyleSheet对象

CSS解析器会将CSS文件解析成StyleSheet对象,下面让我们来看一下CSS到StyleSheet的转换:

这里我们不讲CSS构建的过程,感兴趣的小伙伴可以看一下参考资料里的重学前端,我们简单的介绍一下CSS选择器的特点,这是由CSS设计原则所决定的。

  • 选择器出现的顺序必定跟构建DOM树的顺序一致,即保证选择器在构建到当前节点时,已经可以准确判断该节点所匹配的CSS规则,不需要后续节点信息。

  • CSS样式匹配时是从右向左匹配的,DOM找到它所有匹配的CSS样式后再做加权计算,确定最终样式,所以也就不难理解chrome操作台内样式表信息为何那样展示了。

构建呈现树:整合DOM树和StyleSheet对象为呈现树

构建呈现树时,需要计算每一个呈现对象的可视化属性。每个DOM节点都有一个"attach"方法,在节点插入DOM树时会调用节点的attach方法,计算该节点的样式属性生成呈现器。下面让我们看一下整合(webkit的术语叫‘附加’)的过程:

排版:将呈现器盒子放到对应的位置

所有的呈现器都有一个“layout”或者“reflow”方法,每一个呈现器都会调用其需要进行布局的子代的layout方法。有很多排版方法:正常流文字排版,绝对定位,浮动元素排版,flex排版等。

渲染:把每一个呈现器对应的盒子变成位图

这里的渲染是借用计算机图形学里面的解释,就是把模型变成位图的过程。

位图就是在内存里建立一张二维表格,把一张图片的每个像素对应的颜色保存进去(位图信息也是DOM树中占据浏览器内存最多的信息,我们在做内存占用优化时,主要就是考虑这一部分)。

合成:合成位图,提升性能

这个过程实际上是一个性能考量,它并非实现浏览器的必要一环。合成的过程就是根据合成策略合并位图。合成策略就是最大限度的减少绘制次数,它是“猜测”可能变化的元素,将它排除到合成之外。

目前,主流浏览器一般根据position、transform等属性来决定合成策略,来“猜测”这些元素未来可能发生变化。但是,这样的猜测准确性有限,所以新的CSS标准中,规定了will-change属性,可以由业务代码来提示浏览器的合成策略,灵活运用这样的特性,可以大大提升合成策略的效果。

绘制:将位图绘制到屏幕上,变成肉眼可见的图像的过程

一般来说,浏览器并不需要用代码来处理这个过程,浏览器只需要把最终要显示的位图交给操作系统即可。

到这里我们已经将Webkit主要的工作流程捋了一遍,现在让我们来总结一下,从HTTP请求回来的数据通过HTML解析器和CSS解析器,分别解析成DOM树和StyleSheet对象,然后整合两者生成呈现树,呈现树调用layout进行排版,然后通过渲染将呈现器盒子变成位图,根据合成策略合成位图提升绘制性能,把位图给操作系统让其绘制到屏幕上。看到这里我们很容易就理解了一个小知识点:CSS不会阻塞DOM的解析,但会阻塞DOM的渲染。

现在我们已经以Webkit为例介绍了呈现引擎的主要工作流程,但是我们似乎还遗漏了些什么。对的,Javascript,我们好像一直没有提及当Webkit解析到JavaScript代码时会怎么处理,接下来就让我们一起来看一看这一部分知识吧~~

浏览器加载JavaScript脚本

=================

正常加载流程

浏览器加载JavaScript脚本,主要通过<script>元素完成。其正常流程如下

浏览器的呈现引擎持有渲染的控制权,它正常解析HTML页面 解析遇到<script>标签,呈现引擎移交控制权给Javascript引擎(例如chrome的V8) 如果<script>标签引用了外部脚本那就先下载再执行,否则直接执行代码 JavaScript引擎执行完毕移交控制权给呈现引擎,呈现引擎继续解析 加载外部脚本时,浏览器会暂停页面渲染,等待脚本下载并执行完成后,再继续渲染。原因是 JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。

defer属性

浏览器解析到包含defer属性的<script>元素时,其运行流程如下

  • 浏览器的呈现引擎持有渲染的控制权,它正常解析HTML页面

  • 解析遇到包含defer属性的<script>标签,继续解析HTML,同时并行下载外链脚本

  • 解析完成,文档处于交互状态时开始解析处于deferred模式的脚本

  • 脚本解析完毕后,将文档状态设置为完成,DOMContentLoaded事件随之触发

使用defer属性时需要注意的点:

  • defer属性下载的脚本文件在DOMContentLoaded事件触发前执行(即刚刚读取完标签)

  • defer属性可以保证执行顺序就是它们在页面上出现的顺序

  • 对于内置而不是加载外部脚本的script标签,以及动态生成的script标签,defer属性不起作用

  • 使用defer加载的外部脚本不应该使用document.write方法

async属性

浏览器解析到包含async属性的<script>元素时,其运行流程如下

  • 浏览器的呈现引擎持有渲染的控制权,它正常解析HTML页面

  • 解析遇到包含async属性的<script>标签,继续解析HTML,让另一进程同时并行下载外链脚本

  • 脚本下载完成,浏览器暂停解析HTML,开始执行下载的脚本

  • 脚本执行完毕,浏览器恢复解析HTML

使用async属性时需要注意的点:

  • async属性可以保证脚本下载的同时,浏览器继续渲染

  • async属性无法保证脚本的执行顺序,哪个先下载结束就先执行哪一个

  • 包含async属性的脚本不应该使用document.write方法

  • 如果同时使用async和defer属性,后者不起作用,浏览器行为由async属性决定

脚本的动态加载

<script>元素还可以动态生成,生成后再插入页面,从而实现脚本的动态加载。动态生成的script标签不会阻塞页面渲染,也就不会造成浏览器假死。但是问题在于,这种方法无法保证脚本的执行顺序,哪个脚本文件先下载完成,就先执行哪个。如果想避免这个问题,可以设置async属性为false。还可以监听脚本的onload事件来为脚本指定回调。

CSS阻塞JS加载

因为JS脚本可能会引用DOM的样式做计算,所以为了保证脚本计算的正确性,Firefox浏览器会等到脚本前面的所有样式表,都下载并解析完,再执行脚本;Webkit则是一旦发现脚本引用了样式,就会暂停执行脚本,等到样式表下载并解析完,再恢复执行。

此外,对于来自同一个域名的资源,比如脚本文件、样式表文件、图片文件等,浏览器一般有限制,同时最多下载6~20个资源,即最多同时打开的 TCP 连接有限制,这是为了防止对服务器造成太大压力。如果是来自不同域名的资源,就没有这个限制。所以,通常把静态文件放在不同的域名之下,以加快下载速度。

浏览器预解析

WebKit和Firefox都进行了这项优化。在执行脚本时,其他线程会解析文档的其余部分,找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载,从而提高总体速度。请注意,预解析器不会修改DOM树,而是将这项工作交由主解析器处理;预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。

Emmmm,到这里我们就了解了浏览器的呈现引擎只负责解析HTML和CSS,遇到JS时它会把控制权交给JS的引擎来解析和执行。因为JS引擎拿走了渲染的控制权,所以JS显而易见会阻塞DOM的解析,为了让JS不阻塞DOM的解析浏览器进行了异步加载以及预解析等优化。嗯,我们已经了解了呈现引擎,接下来让我们了解一下它的小伙伴Javascript引擎的工作流程吧~~

Javascript引擎的工作原理

学习笔记

主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue等等

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

HTML/CSS

**HTML:**HTML基本结构,标签属性,事件属性,文本标签,多媒体标签,列表 / 表格 / 表单标签,其他语义化标签,网页结构,模块划分

**CSS:**CSS代码语法,CSS 放置位置,CSS的继承,选择器的种类/优先级,背景样式,字体样式,文本属性,基本样式,样式重置,盒模型样式,浮动float,定位position,浏览器默认样式

HTML5 /CSS3

**HTML5:**HTML5 的优势,HTML5 废弃元素,HTML5 新增元素,HTML5 表单相关元素和属性

**CSS3:**CSS3 新增选择器,CSS3 新增属性,新增变形动画属性,3D变形属性,CSS3 的过渡属性,CSS3 的动画属性,CSS3 新增多列属性,CSS3新增单位,弹性盒模型

JavaScript

**JavaScript:**JavaScript基础,JavaScript数据类型,算术运算,强制转换,赋值运算,关系运算,逻辑运算,三元运算,分支循环,switch,while,do-while,for,break,continue,数组,数组方法,二维数组,字符串

3:**CSS3 新增选择器,CSS3 新增属性,新增变形动画属性,3D变形属性,CSS3 的过渡属性,CSS3 的动画属性,CSS3 新增多列属性,CSS3新增单位,弹性盒模型

[外链图片转存中…(img-8IQeye6L-1714964148513)]

JavaScript

**JavaScript:**JavaScript基础,JavaScript数据类型,算术运算,强制转换,赋值运算,关系运算,逻辑运算,三元运算,分支循环,switch,while,do-while,for,break,continue,数组,数组方法,二维数组,字符串

[外链图片转存中…(img-HgDxRzIr-1714964148514)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值