admin管理员组文章数量:1567811
浏览器工作原理
浏览器的结构
用户界面 —> 浏览器引擎—>渲染引擎
渲染引擎上有: 网络 js解析器 -------->也称浏览器内核
浏览器引擎上有:数据持久层(帮助浏览器存储数据 如cookie等)
各个浏览器的内核
IE —> Trident
Firefox —>Gecko
safari ----> Webkit并开源
Chrome ----->Webkit改造优化的Blink 也开源
Opera与Edge 使用是Blink
进程与线程
进程 是操作系统进行分配资源分配和调度的基本单位,可以申请和拥有计算机资源,进程是程序的基本执行实体。
线程 是操作系统能够进行运算调度的最小单位,一个进程中可以并发多个线程,每个线程并行执行不同的任务
进程之间传递数据 : 通过进程间通信管道IPC传递
应用是多进程的原因是:为了避免某一个进程卡死,而导致应用卡死,因为进程之间相互独立,这样不会影响到整个应用程序。
然后进程通过创建更多线程并行执行不同的任务,同一进程下的线程是可以直接通信共享数据的
单进程带来的问题
1.不稳定: 一个线程出现了问题可能会导致整个进程出问题进而导致浏览器无法正常运行
2.不安全: 因为线程之间是可以随意共享数据 那么一个线程就可以获取整个浏览器的信息
3.不流畅: 一个进程需要负责很多内容,会导致运行效率的问题
多进程的结构
1.浏览器进程
负责控制除标签页外包括地址栏、书签、后退和前进按钮及负责与浏览器的其他进程协调工作
2.网络进程
负责发起接收网络请求
3.GPU进程
负责整个浏览器界面的渲染
4.插件进程
负责控制网络使用的所有插件
5.渲染器进程
负责用来控制显示tab标签内的所有内容(浏览器会默认情况下为每个标签页都创建一个进程)
注意 给每个tab标签创建进程是让它们相互独立 互不影响 当一个标签页卡死不会影响其他标签 页不会使浏览器卡死
在浏览器地址栏输入内容时的浏览的内部变化(本篇重点)
1.浏览器进程的UI线程会捕捉你的输入内容
如果是网址则UI进程会启动一个网络线程来请求DNS进行域名解析,接着开始连接服务器获取数据
如果是一串关键字浏览器就会判断出你是要搜索,于是会使用默认配置的搜索引擎来查询
2.当网络线程获取到数据后
-
会通过SafeBrowsing(谷歌内部的一套站点安全系统)来检测站点是否是恶意站点,如果是,则会提示整个警告页面,告诉你安全隐患,浏览器会阻止你的访问(可强行访问)
-
当检测通过时网络线程会通知UI线程,然后渲染器进程(Render Thread)来渲染页面
-
浏览器进程通过IPC管道将数据传递给渲染器进程的主线程正式进入渲染器进程
-
主线程将html解析构造DOM树–>进行样式计算–>根据DOM树和生成和的样式生成Layout Tree–>通过遍历Layout Tree生成绘制顺序表(paint)–>接着遍历了Layout Tree生成了Layer Tree
然后主线程将将Layer Tree和绘制信息一起传递给合成器线程
合成器线程按照规律进行分图层,并把图层分为更小的图块(tiles)传给栅格线程
栅格化线程 进行栅格化
栅格化完成后合成器线程会通过栅格化线程传递过来的"draw quads"图块信息
根据这些信息合成器线程上合成了一个合成器帧然后将该合成器帧通过IPC传回给浏览器进程
浏览器进程再传递到GPU进行渲染,之后展示到你的屏幕上了
重排
当我们改变一个元素的尺寸位置属性时会重新进行样式计算(Computed Style)布局(Layout)绘制(Paint)以及后面所有的流程
重绘
当我们改变某个的颜色属性时不会触发重排触发布局但还是会触发样式计算和绘制
关于不能大量重排重绘的原因及解决办法
- 动画卡顿原因:
我们可以发现重排和重绘都会占用主线程,还有JS也是运行在主线程上,这样就会引发出现抢占执行时间的问题,如果你写了一段不断导致重排重绘的动画,浏览器则需要在每一帧都运行样式计算布局和绘制的操作,这种情况下会出现动画卡顿是由于js执行时间过长就会导致在下一帧开始时js没有及时归还主线程导致下一帧动画没有按时渲染。
- 解决办法:
1.通过requestAnimationFrame()来解决,它会在每一帧被调用通过API的回调然后我们和把js运行任务分成一些更小的任务块(分到每一帧)在每一帧时间用完前暂停js执行归还主线程,这样在下一帧开始时就可以按时执行布局和绘制 React的渲染引擎React Fiber就用到这个API做了很多优化
2.前面介绍我们可以知道 栅格化的整个流程是不占用主线程的只在合成器线程和栅格线程中运行,这就意味着它无需和JS抢占主线程,多次重排重绘掉帧是因为JS的执行阻塞了主线程,而css中的一个动画属性transform,该属性实现的动画不会经过布局和绘制,而是直接运行在合成器线程和栅格化线程中所有不会受到主线程中JS执行的影响,更重要的是通过transfrom实现的动画由于不需要经过布局绘制样式计算等操作所以节省很多运算时间(方便实现负责的动画)
详解:
渲染器进程把接收到的html、css、js、image等资源渲染成用户可以交互的web页面,渲染器进程的主线程将html进行解析构造DOM(文档对象模型是浏览器对页面在其内部的表示形式是web开发程序员可以通过JS与之交互的数据结构和API)数据结构
html首先经过tokeniser标记化通过词法分析将输入的html内容解析成多个标记根据识别后的标记紧进行DOM数构造,在这个过程中会创建document对象,然后以document的根节点的DOM树不断进行修改向其中添加各种元素 html中会引入额外资源如图片、css、js脚本等,图片和css这些资源需要通过网络下载或者从缓存中直接加载,这些资源不会堵塞html的解析,因为它们不会影响DOM的生成。但当html解析过程中遇到script标签就会停止html的解析流程转而加载解析并且执行js**(原因是js浏览器并不知道js执行是否会改变当前的HTML结构,如果js代码里调用了document.write()修改HTML,哪之前的html解析就没有任何意义了故script标签要放在合适的位置如末尾也可以使用defer和async属性来异步加载js)**
在html解析后我们就会获得一个DOM Tree()树,主线程解析css并确定每个DOM节点的计算样式(注意即使没有提供自定义css样式浏览器也会提供默认样式 比如 h1 标签的自带样式)在dom节点知道每个节点的样式后我们需要知道每个节点放在页面的哪个位置(即该节点的坐标以及该节点需要需要占用多大的区域---->layout布局阶段),主线程通过变量dom和计算好的样式来生成layout Tree,layout Tree每个节点都记录了x,y坐标和边框尺寸(注意layout Tree与DOM Tree 不是一一对应的,重点 有display:none不会出现在layout Tree上会在DOM上有节点 befter 伪类添加的content元素会出现在layout Tree上不会出现在DOM树上 **原因是:**DOM是通过HTML解析获得并不关心样式 而layout Tree是通过DOM和计算好的样式来生成,layout是通过最后展示在屏幕上的节点对应的),
然后我们还需要知道以什么样的顺序绘制(paint)这个节点 (z-index属性会影响节点绘制的层级关系)为了保证在屏幕上展示正确的层级主线程遍历layout Tree创建一个绘制记录表(paint Record)该表记录了绘制的顺序---->绘制阶段,然后到把这些信息转化为像素点显示在屏幕的时候了这种行为被称为栅格化(Restering)
最早的Chrome使用的是只栅格可视区域的内容当用户滚动页面时再栅格化更多的内容来填充缺失的部分 问题展示延迟
现在使用的是合成(Composting),它是一种将页面的各个部分分成多个图层分别对其进行栅格化,并在合成器线程的技术中单独进行合成页面,简单来说就是页面所有的元素按照按照某种规则进行分图层,并把图层都栅格化好了,然后只需要可视化的内容组合成一帧展示给用户即可
最后 主线程遍历Layout Tree生成Layer(图层)Tree 当Layer Tree生成完毕和绘制顺序确定后,主线程将这些信息传递给合成器线程,合成器线程将每个图层栅格化,由于一层可能像页面的整个长度一样大因此合成器线程将他们切分为许多图块 然后将每个图块发送给栅格化线程 栅格化线程栅格化每个图块,并将它们存储在GPU内存中,当图块栅格化完成后合成器线程将收集称为“draw quads”的图块信息,这些信息记录了图块在内存中的位置和在页面的哪个位置绘制图块的信息,根据这些信息合成器线程生成了一个合成器帧,然后合成器Frame(帧) 通过IPC传送给浏览器进程,接着浏览器进程将合成器帧传送到GPU,然后GPU进程渲染展示到屏幕上,当你滚动页面则会重述上面操作生成新的合成器帧等等等
最后
本篇内容根据 我最喜欢的UP主 视频编写完成 请大家多多关注他
objtube的卢克儿
版权声明:本文标题:浏览器工作原理(超级详解!!!!) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1726722697a1081956.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论