从输入URL到渲染页面,浏览器的工作流程

259 阅读5分钟
  1. 用户输入URL,地址栏会判断关键字是搜索内容还是请求的URL地址

    • 如果是搜索内容,地址栏会使用浏览器的默认搜索引擎进行搜索
    • 如果输入的内容符合URL规则,那么地址栏会根据规则,把这段内容加上协议,合成完整的URL
  2. 地址栏回车,浏览器会执行beforeunload,在befoerunload中可以进行数据清理和是否确认离开,比如有未提交的表单就可以取消导航,让浏览器不在执行任何后续的任务

  3. 当前页面没有监听befoerunload或者允许执行,浏览器图标就会变成loading状态,此时浏览器页面依然是之前打开的内容,没有立即替换,这是因为需要等待提交文档阶段,页面内容才会被替换。

  4. 进入网络资源请求过程,浏览器进程通过进程间通信(IPC)将URL请求发送给网络进程,由网络进程发起真正的URL请求,

  5. 网络进程发起请求的流程:网络进程会查找本地是否有缓存资源,如果有则返回缓存资源给浏览器进程;如果没有则进入网络请求流程,第一步进行DNS解析,已获得域名对应的服务器IP地址,如果是HTTPS请求,还要建立TLS连接

  6. 利用IP地址和服务器建立TCP连接,建立连接之后,浏览器会构建请求行、请求头、请求体,并把和域名相关的Cookie等数据添加到请求头中,向服务器发送请求信息;

  7. 当接收到服务器返回的请求头信息,网络进程会对请求头进行解析,

    • 当状态码为301或者302时,表示服务器要求浏览器重定向到其他URL地址,可以通过请求头的Location字段获取重定向地址,然后发起新的HTTP或者HTTPS请求,一切又重头开始;
    • 当服务器返回的请求头状态码是200,表示可以继续处理该请求
  8. 网络进程将响应数据(行、头、体)通过进程间通信(IPC)发送给浏览器进程

  9. 响应数据类型处理,浏览器进程会根据响应头Content-Type字段判断服务器返回的数据是什么类型的数据,比如Content-Type: text/html(html页面);applaction/octet-stream(字节流类型)

  10. 渲染进程的准备:

    • 默认情况下浏览器会为每个打开的页面创建一个新的渲染进程,但是也有例外情况,当页面同属一个站点时,他们会公用一个渲染进程,同一个站点定义为跟域名和协议相同,还包括了根域名下的所有子域名和端口号

      以下都为统一站点

      time.geekbang.org www.geekbang.org www.geekbang.org:8080

    • 渲染进程准备完之后,还不能立刻进入文档解析状态,因为此时数据还在网络进程中,并没有提交到渲染进程中,因此下一步要进行提交文档阶段

  11. 提交文档阶段:就是浏览器进程将网络进程接受的相应数据提交给渲染进程,具体流程如下

    • 当浏览器进程接收到网络进程发送的响应数据后,会想渲染进程发送‘提交文档’的消息
    • 渲染进程接收到提交文档消息后,与网络进程建立数据管道
    • 当数据传输完毕后,渲染进程会想浏览器进程发送确认提交消息
    • 浏览器接收到确认提交之后,会进行更新操作,包括更爱URL地址、前进后退的历史状态、web页面、安全状态
  12. 这样就解释了为什么输入一个URL地址回车后没有马上加载新页面的原因

  13. 以上导航阶段就结束了

  14. 进入渲染阶段:由于渲染阶段十分复杂,所以把它划分成不同的子阶段,有不同的子阶段完成,把它称作渲染流水线

  15. 渲染流水线分为以下几个子阶段:构建DOM树、样式计算、布局阶段、分层、绘制、分块、合成、栅格化;其中每个阶段需要重点关注的内容是:输入内容、处理阶段、输出内容

    • 构建DOM
      • 因为浏览器不能直接识别HTML,需要通过html解析器解析成DOM树,保存在内存中,可以通过js对DOM树进行增删改查
      • 这一阶段的输入内容是HTML,处理阶段是html解析器解析;输出内容是DOM树
    • 样式计算
      • 浏览器不能识别css文本(link、style、行内style),需要转换成stylesheets
      • 样式属值性标准化例如font-size:2rem =》font-size:20px;
      • 计算出DOM树每个节点的样式:涉及到继承和层叠样式
    • 布局阶段:计算出DOM树中可见元素的几何位置信息
      • 创建布局树:只包含可见元素的布局树
      • 布局计算:计算出布局树每个节点的坐标,在这个阶段布局树既是输出内容,也是输入内容,是不合理的地方,因为没有把输入内容与输出内容划分开来
    • 分层:创建图层数
    • 绘制:
  16. 为什么减少重排重绘会提高web性能?

    • 首先渲染阶段很复杂,所以渲染引擎将其划分了不同的子阶段,分别为:创建DOM、样式计算、布局阶段、分层、绘制、分块、光栅化、合成
    • 减少重排重绘就是减少这些子阶段的工作次数,减少对浏览器进程的占用
    • 如果多次重排重绘就会增加每一帧的工作量,当时间超出每一帧的是时间(16ms)页面就会出现卡顿
    • 减少重排重绘的方法
      • 尽量使用transform属性改变元素的几何信息
      • 尽量使用class而不是style改变样式
      • dom属性读写分离
      • 批量处理dom属性
      • fragment