前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浏览器渲染(线程视角1)

浏览器渲染(线程视角1)

原创
作者头像
醉酒鞭名马
修改2020-05-23 22:29:08
2.3K3
修改2020-05-23 22:29:08
举报

这篇文章主要从渲染进程的的视角,来看渲染过程,主线程做了那些事情,导航流程、GPU快速栅格化图像和浏览器主进程输入到显卡后缓冲区部分一带而过,之后文章详细介绍

上一篇 浏览器渲染(进程视角)文章从浏览器的进程模型演进分析了打开一个页面的渲染进程数量,及每个渲染页面的连接,上下文组等内容,那么对于渲染进程内所作的事情怎样的呢?

页面生成流程
页面生成流程

页面生成流水线

如上图页面生成过程中进程之间的关系如下:

  • 当用户在地址栏输入地址时,浏览器主进程处理输入信息(是输入内容还是请求url,如果是url,拼装协议),回车后的事件触发(before unload),启动加载状态,把url请求发送给网络进程
  • 网络进程收到url请求后,开始构建请求信息,查找本地副本资源缓存,查找缓存失败准备发起请求
    • ip地址和端口的查找(查找dns缓存,失败直接查找dns)
    • tcp连接(如果同域名请求大于6个,放入队列等待)
    • 发起http请求
    • 服务器处理请求返回信息
    • 处理响应头(重定向等操作),如果是html发送消息给浏览器进程准备渲染进程
    • 接受数据,直接发送给渲染进程(浏览器进程确认文档被提交后,会建立网络进程和渲染进程的数据通道)
  • 渲染进程收到提交文档消息后,开始不断接受网络进程数据进行渲染流程
  • 渲染进程在合成阶段利用GPU进程快速生成位图,一旦所有的图块都被栅格化完成,将提交命令DrawQuad

给浏览器进程

  • 浏览器接收DrawQuad命令将页面绘制到内存中然后提交到显卡的后缓冲区
  • 显示器以60HZ的频率不断从显卡前缓冲区读取图像,GPU会将显卡前缓冲区和后缓冲区不断的互换,以达到显示器中读取最新的图片


页面渲染流水线

接下来看今天文章的重点,渲染流水线

渲染过程
渲染过程

渲染进程要做的事情大部分由主线程, IO线程,合成线程,光栅化线程池配合网络进程,浏览器进程,GPU进程完成一帧图像的绘制,其中IO线程主要负责和网络进程、浏览器主进程之间的交互将任务添加到消息队列尾部,主线程通过循环机不断地消费任务队列中的任务,按照渲染的时间顺序,渲染流水线可分为如下几个子阶段:构建 DOM 树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成。

构建DOM树

当网络进程接收到http响应头内容为Content-Type: text/htmls时,发送消息给浏览器进程,浏览器进程开始加载渲染进程,并为网络进程和渲染进程数据通道,将html字节流实时发送给渲染进程,DOM就是对html文档结构的一个表述

DOM树
DOM树

DOM树

  • DOM是生成页面的基本数据结构
  • DOM提供改变文档、样式、内容的接口
  • DOM是一道安全防线,在解析过程中如果有不安全的内容会被拒绝

HTML解析器

html文档要经过htmlpaser处理转换成最终的dom树,HTML解析器并不是等待整个文档加载完成之后在解析结构,而是从网络进程和渲染进程建立的数据管道不断的读取解析。大概可以过程如下:

html解析过程
html解析过程

html解析器执行过程分为三个阶段:

  • 通过分词器(词法分析)将html字节流转换为token
  • 将token转换为dom需要的节点
  • 将节点添加到document树

Token栈

html解析器维护了一个token栈结构,主要用来计算节点之间的父子关系,按照字节流的顺序入栈、出栈将字节流进行分词。token将标签和文本划分为 tagTokentextToken ,tagToken又分为startTokenendToken 一个简单的例子:

代码语言:javascript
复制
<html>
<body>
    <div>
        <h2>text3</h2>
        <p>text4</p>
    </div>
</body>
</html

按照顺序,分词器会将标签和文本解析为如下的token

token入栈顺序
token入栈顺序

接下来token栈和dom树生成的过程

token栈
token栈
  • html解析器开始工作时,会先创建一个根为document的空DOM结构
  • 分词器解析出来是startTag Token时,把startTag token压入栈中(图中的1-4步骤),并为该token创建一个DOM节点,加入到DOM树中,它的父节点就是栈中相邻的节点
  • 如果分词器解析出来的是文本token(例如图中的第5步骤),那会直接生成一个文本节点,不需要再压入栈中,它的父节点就是当前栈顶token所对应你的DOM节点

EndTag StartTag对比出栈
EndTag StartTag对比出栈
  • 如果分词器解析出来endTag token时,会从token栈顶元素对比,如果是对应的startToken,将startTag Token从栈顶弹出,解析完成一个标签

JS脚本阻塞DOM生成

上文已经介绍html解析器是按照顺序进行分词解析标签,当遇到js文件、js内嵌脚本时会阻塞DOM

当遇到js文件时

  • 当解析到js标签<script>有src属性,暂定dom解析,因为渲染进程并不知道js是否有对dom的接口操作
  • 网络进程下载js文件,渲染进程必须等待js下载完成(网络耗时,js大小都是耗时点)

当遇到内嵌脚本

  • html解析器解析到内联脚本,暂停dom解析,js引擎执行脚本,修改已生成的dom结构、内容,脚本执行结束,html解析器恢复继续执行

css样式优先下载解析

  • js引擎在解析执行脚本之前,并不知道是否有操作document.styleSheets 的接口,所以不管js有没有操作cssom,都要先下载css,解析css,在执行js脚本

优化js脚本阻塞DOM

js阻塞dom的耗时点在网络下载、js文件的大小,所以从网络层面,js体积优化

  • 下载加速:cdn加速,如果js没有操作dom可以使用异步加载async/defer,开启预解析线程
  • 体积减小:压缩js文件大小,去掉注释,利用es module的静态分析webpack等工具去掉无用包引入

未完,渲染子阶段待续...

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 页面生成流水线
  • 页面渲染流水线
    • 构建DOM树
      • DOM树
        • HTML解析器
          • Token栈
        • JS脚本阻塞DOM生成
          • 当遇到js文件时
          • 当遇到内嵌脚本
          • css样式优先下载解析
          • 优化js脚本阻塞DOM
      相关产品与服务
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档