前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【浏览器渲染原理】

【浏览器渲染原理】

作者头像
CODER-V
发布2023-03-11 09:54:36
7120
发布2023-03-11 09:54:36
举报
文章被收录于专栏:藏经阁

1 浏览器框架结构

  1. 用户界面:就是浏览器自带的呈现给用户的一些标签界面,包含一些标签收藏夹等用于用户提升浏览器体验的功能UI
  2. 浏览器引擎:用于在用户界面和渲染引擎之间,传递数据。浏览器引擎下还有个数据持久层子模块,帮助浏览器存储各种数据,cookie、storage…
  3. 渲染引擎:负责渲染用户通过HTTP请求获取的内容。渲染引擎下边还有很多子模块:
    • 网络模块:负责网络请求
    • JS解析器:解析和执行js代码

渲染引擎也称内核是浏览器的核心。

2. 进程与线程关系

浏览器是一个运行在操作系统上的应用程序,每个应用程序必须至少启动一个进程来执行其功能,每个程序往往又会执行很多任务,那么进程就会创建很多线程来执行这些小的任务。

当我们在启动某个应用程序的时,就会创建一个进程来执行任务代码,同时会为该进程分配内存空间,该应用程序的状态都保存在该内存空间里。当应用关闭时,该内存空间就会被回收。

程序可以启动更多的进程来执行任务,由于每个进程分配的内存空间是独立的,如果两个进程之间需要传递某些数据,则需要进程通信管道IPC来传递。很多应用程序都是多进程的结构,这样是为了避免某一个进程卡死,影响整个应用程序,因为进程之间相互独立,一个进程卡死不会影响用户使用另一个进程。

进程可以将任务分成更多细小的任务,然后通过创建多个线程并行执行不同的任务,同一个进程之间的线程是可以直接通信共享数据的.

3. 早期浏览器结构

目前的浏览器都是多进程的结构,但是早期的浏览器都是单进程的结构。 但这一个进程也有多个线程:

  • 页面线程:负责页面渲染和展示
  • JS线程:执行js代码
  • 还有其他各种线程

但是单进程结构有几个问题: ① 不稳定:其中一个线程卡死,会导致整个进程出问题。比如你打开多个标签页,其中一个标签页卡死,可能会导致整个浏览器无法运行。 ② 不安全:浏览器之间是可以共享数据的,那么js线程就可以访问浏览器里的所有数据 ③ 不流畅:一个进程需要负责太多事情,导致运行效率不佳

4. 现代浏览器结构

为了解决早期浏览器的问题,现代浏览器采用了多进程架构,根据进程功能不同来分解浏览器:

  • 浏览器进程:控制除标签页面以外的用户界面,包括地址栏、书签、前进、后退等,以及负责与浏览器的其他进程协调工作
  • 网络进程:发起接收网络请求
  • GPU进程:负责整个了浏览器界面的渲染
  • 插件进程:负责控制网站使用的所有插件,这里的插件不是指安装的拓展
  • 渲染器进程:控制显示tab标签内的所有内容,浏览器默认情况下可能会为每一个标签页都创建一个进程,因为这和用户启动浏览器时选择的进程模型有关,一共有4种进程模型:
    • 默认进程:为每一个标签页创建一个进程
    • 同一站点使用同一进程,
    • 一个tab里的所有站点使用同一个进程
    • 浏览器引擎和渲染引擎共用一个进程

5 浏览器渲染原理

  1. 当我们在地址栏输入地址时,浏览器的UI线程会捕捉我们的输入内容, a. 若访问的是网址,则UI线程会启动一个网络线程来处理请求DNS和域名解析,接着开始连接服务器获取数据; b. 若输入的不是网址,而是关键词,会启动默认配置的搜索引擎来查询。
  2. 网络线程从服务器获取到数据后的操作: a. 当网络线程获取到数据后,会通过SafeBrowsing先检查站点是否恶意站点,如果是,则会展示一个警告页面,告诉你这个站点有安全问题,浏览器会阻止你的访问,当然你也可以强行访问; b. 当访问的数据准备完毕并且安全校验通过时,网络进程会通知UI进程; c. UI进程会创建一个渲染进程来渲染页面,浏览器进程通过IPC管道将数据传递给渲染器进程,正式进入渲染流程; d. 渲染器进程接收到的数据,也就是HTML,渲染器进程的核心任务就是把HTML、CSS、JS、静态资源等,资源渲染成用户可以交互的Web页面:
    1. 构造DOM树:渲染器进程的主进程将html进行解析,通过词法分析,构造DOM数据结构:创建document对象,然后以对document对象为根节点的DOM树不断修改,向其中添加各种元素;
    2. 下载静态资源:css、图片等静态资源通常都是通过网络下载或从缓存中直接加载,不会阻塞html的解析,不会影响DOM结构的生产;
    3. js阻塞:但是在解析过程中遇到script标签时,就会停止html解析,转而去加载解析并执行js(因为浏览器并不知道当前的js操作会不会改变当前的html结构,如果js代码里用例document.write()来修改html,那么之前的解析就都没有意义了,所以我们一定要把script标签放在合适的位置,或者使用async或deffer属性来异步加载执行js);
    4. 计算UI:在html解析完成后,就会得到一个DOM树,但此时还不知道DOM树的每一个节点的样式,主线程需要解析css并确定每个节点的就算样式,即使你没有提供自定义的css样式,浏览器也有默认的样式表;
    5. layout布局:在知道节点的样式后,我们需要计算节点在页面的坐标位置以及占用空间。主线程通过遍历DOM和计算好的样式来生产Layout Tree,Layout Tree上的每个节点都记录了节点坐标和尺寸大小,但是DOM Tree中设置了display: none属性的节点并不会出现在Layout Tree上,而添加了 ::before的伪元素,其内容会出现在Layout Tree上不会出现在DOM Tree上。因为DOM是通过html解析获得的并不关心样式,而Layout tree是通过DOM和计算好的样式来生产的,Layout Tree就是最后展示给用户的UI界面;
    6. 绘制:比如z-index属性影响节点绘制的层级关系,若按照dom的层级结构来渲染页面,则会导致错误的渲染,所以为了保证节点绘制的层级,主线程遍历Layout Tree创建了一个绘制记录表(Paint Record),该表记录了绘制的顺序;
    7. 栅格化:将Layout Tree转化成像素点显示在屏幕上(过程复杂,不研究)。就是用户看到的效果了。

6. 渲染问题

  1. 当我们改变一个元素的位置尺寸时,会重新进行样式计算、布局、绘制、栅格化等流程(重排)。
  2. 当我们改变某个元素的颜色属性时,不会触发重新布局,但是会触发样式计算和绘制(重绘)。

解决方案: js、重排、重构都是在主线程上执行的,如果浏览器不断的重排、重绘,浏览器会在每一帧(浏览器滚动是以帧为单位的动画)上都进行计算布局、绘制的操作。若在上一帧的js还没有执行完,就滚动到了下一帧,会导致下一帧动画没有及时渲染,就会造成页面卡顿。

  1. requestAnimationFrame() 会在每一帧执行完之前,结束js的执行,这样下一帧就能及时绘制。react最新渲染引擎React Fiber就使用了这个方法做了很多优化。
  2. transform。css中transform属性实现动画不会导致页面重绘、重排问题。它直接在合成器线程和栅格化线程中运行,这就意为着它无需和js线程抢夺主线程。更重要的是,通过transform实现的动画不需要经过绘制、布局、样式计算等操作,节省了很多时间。

SafeBrowsing(谷歌内部的站点安全系统):通过检查该站点的数据来检测该站点是否安全,比如通过查看站点IP是否在谷歌的黑名单之内。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 浏览器框架结构
  • 2. 进程与线程关系
  • 3. 早期浏览器结构
  • 4. 现代浏览器结构
  • 5 浏览器渲染原理
  • 6. 渲染问题
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档