互联网会发生

image.png

使用 域名访问 Web服务器

浏览器发现网址不是 IP 地址,会发起域名解析动作。通过访问一系列的域名解析的过程,试图把域名翻译成 TCP/IP 协议的 IP 地址。
域名解析过程:

  1. 浏览器缓存
  2. 操作系统缓存
    1. hosts 文件可以覆写
  3. 访问域名解析服务器

    使用 IP 地址访问 Web服务器

    HTTP 协议是运行在 TCP/IP 基础上的,依靠 TCP/IP 协议来实现数据的可靠传输。
    所以浏览器要用 HTTP 协议收发数据,首先要做的就是建立 TCP 连接。

简要叙述一下一次最简单的浏览器 HTTP 请求过程:

  1. 浏览器从地址栏的输入中获得服务器的 IP 地址和端口号;
  2. 浏览器用 TCP 的三次握手与服务器建立连接;
  3. 浏览器向服务器发送拼好的报文;
  4. 服务器收到报文后处理请求,同样拼好报文再发给浏览器;
  5. 浏览器解析报文,渲染输出页面;

浏览器的工作

  • 用户界面
  • 浏览器引擎
    • 数据持久层
  • 渲染引擎
    • 网络
    • JS 解析器

      多进程的浏览器

      单进程浏览器

  1. 不稳定

如果有一个页面卡死可能会导致整个浏览器

  1. 不安全
    浏览器之间是可以共享数据
  2. 不流畅
    负责太多事情会导致运行效率问题

    多进程结构

    浏览器进程
  • 控制除标签页外的用户界面
  • 包括地址,书签,后退,前进按钮等
  • 以及负责与浏览器其他进程负责协调工作

缓存进程
网络进程

  • 负责发起网络请求

GPU 进程

  • 整个浏览器页面渲染

插件进程

  • 整个网页所使用到的插件,如 flash

渲染器进程

浏览器输入地址时

浏览器进程 UI 线程会捕捉输入内容,
如果输入是网线,则 UI 线程启动一个网络线程请求 DNS 进行域名解析,连接服务器获取数据
如果输入是关键词,于是会使用默认配置的搜索引擎来查询

网络线程获取到数据之后的工作

  1. 通过 SafeBrowsing 检查网站是否为恶意站点
    • 如果是浏览器提示警告页面
      • 告诉安全问题
      • 并会阻止访问
  2. 通过检查后,网络线程会通知 UI线程
    1. UI 线程会创建渲染器进程来渲染页面
    2. 浏览器进程通过 IPC 管道将数据传给渲染器进程
  3. 正式进入渲染流程
    • 渲染器进线把 HTML / CSS / JS / 图片 等资源渲染为用户可以交互的 WEB 页面
      • 将 HTML 解析,得到 DOM Tree
        • 构造 DOM 数据结构
          1. Tokeniser 标记化,把 HTML 解析成多个标记
          2. DOM 树构造,通过标记生成
            1. 当遇到脚本,会停止 HTML 解析流程
          3. DOM 生成 document 对象
      • 解析CSS
        • 样式计算
        • 解析样式
      • 生成 Layout Tree 布局
        • DOM Tree 与 Layout Tree 不一定一一对应
          • display : none 不会出现在 Layout Tree
          • 伪类不会出现在 DOM Tree
      • 遍历 Layout Tree 创建绘制记录表 Paint
        • 代表绘制的顺序
      • 把信息传递给 合成器线程
        • 栅格线程
          • 进行栅格化,把信息转化成像素点
          • 生成合成器帧Frame
    • 通过 IPC 把合成器帧交给浏览器进程
    • 再由浏览器进程把合成器帧传送到 GPU
    • GPU 渲染展示到屏幕上

当页面发生变化,都会生成一个新的合成器帧 传给GPU进行渲染

浏览器的渲染工作总结

image.png

  1. 主线程
    1. 将 HTML 解析构造 DOM 树
    2. 进行样式计算 Style
    3. 由 DOM 和 style 生成 Layout Tree
    4. 遍历 Layout Tree 生成绘制顺序表 Paint
    5. 遍历 Layout Tree 生成图层 Layer
  2. 合成器线程把图层分为更小的图块 Tiles
  3. 栅格线程
    1. 栅格化 raster
    2. 发送 draw quads 图块信息
  4. 合成器线程生成合成帧 Frame
  5. IPC 传给浏览器进程
  6. 浏览器进程再传给 GPU 进行渲染

    重排

    如改变元素的宽度,会重新进行以上的操作

    重绘

    如改变元素的背景颜色,会除 布局 Layout 和 生成图层 Layer 之外的操作

    引出动画问题

    JavaScript 也会在主线程中运行,会与重排和重绘抢占执行时间的问题。
    一个不断导致重排重绘的动画,浏览器需要在每一帧都运行样式计算布局中和绘制的操作。而在以每秒 60 帧的刷新才不肢让用户感觉而在卡顿,如果在运行动画时还有大量的 JS 任务需要进行。
    在一帧的时间内布局和绘制结束后,还有剩余时间 JS 就会拿到主线程的使用权。如果 JS 的执行时间过长,会导致在下一帧动画没有按时渲染,就会出现动画的卡顿。

    优化手段

  7. requestAnimationFrame()

会在每一帧被调用,把 JS 任务分成一些更小的任务块(分到每一帧),在每一帧时间用完前暂停 JS 执行,归还主线程。
React Fiber 用了这 API 做了很多优化

  1. CSS 的 Transform

栅格化的整个流程是不占用主线程,只在合成器线程和栅格化线程中运行,无需与 JS 抢夺主线程。
通过 CSS Transform 属性实现动画不会经过布局和绘制,而是直接运行在合成器线程和栅格线程中,不会受主线程中 JS 执行的影响。更重要是 Transform 实现的动画由于不需要经过布局绘制样式计算等操作,节省很多运算。