Skip to content

浏览器渲染

浏览器主要组成与浏览器线程

  • 界面控件(User Interface):包括地址栏,前进后退,书签菜单等窗口上除了网页显示区域以外的部分
  • 浏览器引擎(Browser engine):查询与操作渲染引擎的接口
  • 渲染引擎(Rendering engine):负责显示请求的内容。比如请求到的HTML,它会负责解析HTML、CSS 并将结果显示到窗口中
  • 网络(Networking):用于网络请求,如HTTP请求。它包括平台无关的接口和各平台独立的实现
  • UI后端(UI Backend):绘制基础元件,如组合框与窗口。它提供平台无关的接口,内部使用操作系统的相应实现
  • JS解释器(JavaScript Interpreter):用于解析执行JavaScript代码
  • 数据存储持久层(Data Persistence):浏览器需要把所有数据存到硬盘上,如cookies。新的HTML5规范规定了一个完整(虽然轻量级)的浏览器数据库web database

Chrome浏览器中进程

  • 浏览器进程: 负责控制浏览器除标签页外的界面,包括地址栏、书签、前进后退按钮等,以及负责与其他进程的协调工作,同时提供存储功能
  • GPU进程:负责整个浏览器界面的渲染。Chrome刚开始发布的时候是没有GPU进程的,而使用GPU的初衷是为了实现3D CSS效果,只是后面网页、Chrome的UI界面都用GPU来绘制,这使GPU成为浏览器普遍的需求,最后Chrome在多进程架构上也引入了GPU进程
  • 网络进程:负责发起和接受网络请求,以前是作为模块运行在浏览器进程里面的,后面才独立出来,成为一个单独的进程
  • 插件进程:主要是负责插件的运行,因为插件可能崩溃,所以需要通过插件进程来隔离,以保证插件崩溃也不会对浏览器和页面造成影响
  • 渲染进程:负责控制显示tab标签页内的所有内容,核心任务是将HTML、CSS、JS转为用户可以与之交互的网页,排版引擎 Blink 和 JS 引擎 V8 都是运行在该进程中,默认情况下Chrome会为每个Tab标签页创建一个渲染进程

渲染进程中的线程

  • GUI渲染线程:负责渲染页面,解析html和CSS、构建DOM树、CSSOM树、渲染树、和绘制页面,重绘重排也是在该线程执行。在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,GUI更新会被保存在一个队列中等到引擎线程空闲时立即被执行。
  • JS引擎线程:一个tab页中只有一个JS引擎线程(单线程),负责解析和执行JS,处理页面中用户的交互,以及操作DOM树、CSS样式树。它GUI渲染线程不能同时执行,只能一个一个来,如果JS执行过长就会导致阻塞掉帧 GUI渲染线程与JS引擎线程互斥
  • 计时器线程:指 setInterval 和 setTimeout,因为JS引擎是单线程的,所以如果处于阻塞状态,那么计时器就会不准了,所以需要单独的线程来负责计时器工作
  • 异步http请求线程: XMLHttpRequest连接后浏览器开的一个线程,比如请求有回调函数,异步线程就会将回调函数加入事件队列,等待JS引擎空闲执行
  • 事件触发线程:主要用来控制事件循环,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

渲染流程

  • 解析HTML生成DOM树 - 渲染引擎首先解析HTML文档,生成DOM树
  • 构建Render树 - 接下来不管是内联式,外联式还是嵌入式引入的CSS样式会被解析生成CSSOM树,根据DOM树与CSSOM树生成另外一棵用于渲染的树-渲染树(Render tree)
  • 布局Render树 - 然后对渲染树的每个节点进行布局处理,确定其在屏幕上的显示位置
  • 绘制Render树 - 最后遍历渲染树并用UI后端层将每一个节点绘制出来

关键的渲染路径与阻塞渲染

  • CSS 被视为渲染阻塞资源 (包括JS) ,这意味着浏览器将不会渲染任何已处理的内容,直至 CSSOM 构建完毕,才会进行下一阶段。
  • JavaScript 被认为是解释器阻塞资源,HTML解析会被JS阻塞,它不仅可以读取和修改 DOM 属性,还可以读取和修改 CSSOM 属性。

优化渲染性能

  • 优化JS的执行效率
  • 降低样式计算的范围和复杂度
  • 避免大规模、复杂的布局
  • 简化绘制的复杂度、减少绘制区域
  • 优先使用渲染层合并属性、控制层数量
  • 对用户输入事件的处理函数去抖动(移动设备)

参考资料