《浏览器工作原理与实践》学习笔记(一)

2020-02-11  本文已影响0人  VioletJack

本文是极客时间上《浏览器工作原理与实践》课程的学习笔记。

进程和线程

一个进程就是一个程序的运行实例。
线程是依附于进程的,而进程中可以使用多线程并行处理提升运算效率。

进程特点

浏览器的单进程架构

早期的浏览器是单进程的,一旦出错整个浏览器都挂了。

浏览器的多进程架构

多进程架构的缺点

未来面向服务的架构

原来的各种模块会被重构成独立的服务,每个服务都可以在独立的进程中运行,访问服务必须使用定义好的接口,从而构建一个更内聚、松耦合、易于维护和扩展的系统。


网络加载速度是非常影响首屏渲染速度的。

数据包通信过程

互联网实际上是一套理念和协议组成的体系架构。其中协议是一套众所周知的规则和标准,如果各方统一使用,那么他们之间的通信将变得毫无障碍。

  1. 先为数据包加上 IP 头,IP 头存储了发送和接收主机的计算机地址。
  2. IP 协议负责把数据包传送到对方电脑,而 UDP 可以通过端口号将数据包传递给应用程序。
    端口号信息会被放到 UDP 头里面,进行传输。

UDP 协议对于发生错误的包不提供重发机制,只是丢弃当钱包。
UDP 不能保证数据的可靠性,但是传输速度非常快。

  1. 如果是需要传输可靠性的应用,就要引入 TCP 协议了。

TCP 提供了数据包的排序机制,避免丢包。
TCP 提供了丢失数据包的重传机制。
TCP 传输的完整过程为

  • 建立连接 —— 三次握手
  • 传输数据 —— 保证数据包的有序性和完整性,提供重发、【爱旭机制。
  • 断开连接 —— 四次挥手

TCP 和 HTTP 的关系:TCP 负责数据包的完整传输,HTTP 负责报文信息的构建和解析。他们都属于 TCP/IP 协议簇。


HTTP 是一种允许浏览器向服务器获取资源的协议,是 web 的基础。

浏览器发起 HTTP 请求的流程

  1. 构建请求 —— 请求行、请求头
  2. 查找缓存 —— 如果有有效缓存直接使用缓存。
    3, 准备 IP 地址和端口 —— 建立 TCP 连接,传输 HTTP 协议的数据。

浏览器会请求 DNS 返回域名对应的 IP,当然也可以是 DNS 数据缓存服务。
获取端口号,如果没有指明端口号 HTTP 协议默认是 80 端口。

  1. 等待 TCP 队列 —— chrome 一个域名同时最多只能建立 6 个 TCP 连接。
  2. 建立 TCP 连接 —— 三次握手
  3. 发送 HTTP 请求 —— HTTP 请求报文有请求行、请求头、请求体。

服务器处理 HTTP 请求流程

  1. 返回请求 —— 请求处理结束,返回数据给浏览器。

可以使用 curl 来查看返回请求数据
返回数据符合 HTTP 响应数据的格式。

  1. 断开连接 —— 浏览器拿到数据,通常情况下就可以挥手断开连接了。

可以加上 Connection: Keep-Alive 来保持连接。保持 TCP 连接可以省去下次请求时需要建立连接的时间,提升资源加载速度。

重定向

如果是一个需要重定向的网络请求,那么会涉及到重定向操作。响应中有 3xx 的状态码的情况一般就涉及到重定向了。
重定向的目标地址在响应头的 Location 中,浏览器会自动跳转到 Location 提供的地址再次发起一次 HTTP 请求。

如何确定用户登录信息

通过 cookie 或者 header 传递用户 uid 或者 token 之类的随机码。

HTTP 请求从发起到结束:

如何排查请求过慢的问题

1 首先猜测最可能的出问题的地方,网络传输丢包比较严重,需要不断重传。然后通过ping curl看看对应的时延高不高。
2 然后通过wireshake看看具体哪里出了问题。
3 假如别人访问很快,自己电脑很慢,就要看看自己客户端是否有问题了。


浏览器访问网页需要各个进程间的通力协作

在浏览器里,从输入 URL 到页面展示,中间发生了什么?

  1. 打开浏览器
  2. 用户在地址栏输入内容
  3. 解析输入内容

有效 URL :在 URL 前面加上协议头。
文本内容:使用浏览器默认搜索引擎,合成带搜索关键字的搜索引擎 URL。

  1. 回车

tips:在页面替换前会调用一次 beforeunload 事件允许页面在退出前执行一些操作。

  1. url 请求

把 URL 通过 IPC 发送到网络进程
查找本地缓存资源
没有缓存,进行 DNS 解析获取域名对应 IP
如果是 HTTPS,那么需要建立 TLS 连接。
建立 TCP 连接
发送 HTTP 请求
收到 HTTP 响应
响应内容解析

  • 如果存在重定向行为 —— 出现 301、302 之类信息,根据 Location 再次发起新的 HTTP 或 HTTPS 请求。
  • 响应数据类型处理 —— 通过 Content-Type 这个 HTTP 头来告诉浏览器返回的响应体数据类型,并且浏览器会根据 Content-Type 的值来决定如何显示响应体的内容。
    text/html 展示 HTML 页面
    application/octet-stream 显示数据为字节流类型,浏览器会按照下载类型来处理。
    不同的 Content-Type 浏览器会有不同的后续操作
    下载类型:浏览器会进行下载操作
    内容类型:像图片、文本这些,会直接解析展示。
    HTML 类型:那么就会有后续的操作~
  1. 准备渲染进程

通常情况下每个页面都会被分配到一个渲染进程。
如果符合“同一站点”策略,那么多个标签页会共用一个渲染进程。

  1. 提交文档 —— 将网络进程接收到的 HTML 数据提交给渲染进程。

浏览器进程收到网络进程数据,告诉渲染进程提交文档。
渲染进程和网络进程建立传输数据的管道
传输完成后,渲染进程告诉浏览器进程确认提交。
浏览器收到确认提交消息,更新浏览器界面状态,并更新 Web 页面。
PS:这里包含了很多教程间的通信啊,浏览器并非一个整体啊。到这里浏览器 UI 已经发生了改变(先请求数据,再更改浏览器 UI,再渲染 web 页面)。

渲染阶段

HTML 文档解析
构建 DOM 树
计算 CSS 属性
合并 CSSOM
排版
绘制
合并
………

默认端口号

HTTP 是 80,HTTPS 是 443。

tips

其实看课程评论也非常精彩的!


页面渲染是什么?

HTML 定义页面元素和结构
CSS 定义页面元素的样式。
JavaScript 可以对网页内容进行操作。

渲染流水线

构建 DOM 树

将 HTML 转换为浏览器能够理解的接口:DOM 树

样式计算

计算出每个元素的具体样式

把 CSS 转换为浏览器能够理解的结构
获取 CSS 的途径

浏览器无法直接理解纯文本的 CSS 样式,所以渲染引擎会将 CSS 文本转换为浏览器可以理解的结构 styleSheets
转换样式表中的属性值,使其标准化。像:12px,rgb(0, 0, 0)等等。
计算出 DOM 树中每个节点的具体样式。
CSS 继承:每个 DOM 节点都包含有父节点的样式。
CSS 层叠:定义了如何合并来自多个源的属性值的算法。
如果不提供任何样式,浏览器会使用 UserAgent 默认样式。

布局阶段

计算出 DOM 树中可见元素的几何位置。

创建布局树 —— 在显示之前,要额外构建移柯只包含可见元素的布局树。
遍历 DOM 树中的所有课件节点,并把这些节点加到布局树中;
布局计算 —— 计算布局树节点的坐标位置。

分层

区分图层,参考 PS

渲染引擎需要为特定的节点生成专用的图层,并生成一颗对应的图层树。
类似于 PS,浏览器的页面实际上被分成了很多图层,这些图层叠加后合成了最终的页面。
并非布局树的每个节点都包含一个图层,如果节点没有对应的层,就会合并到父级。
什么情况下会有单独图层?

图层绘制

所有的属性绘制都是通过一条条单独的指令去实现的。

栅格化

在做完图层布局、分层、绘制一系列操作后,渲染进程会将操作指令提交给合成线程。
合成线程会将图层划分为图块。(一个页面也许会很长,那么会被分割成很多固定宽高的图块。)
合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。
栅格化过程通常会使用 GPU 来加速生成。

合成

当所有位图被光栅化,合成线程会生成一个绘制图块的命令,提交给浏览器进程。
这时候会可以看到漂亮的页面啦~

渲染过程

将 HTML 转为 DOM 树
将 CSS 转为 styleSheets,计算出 DOM 节点的样式。
创建布局树,计算元素的布局信息。
对布局树分层,生成分层树。
为每个图层生成绘制列表,并将其提交给合成线程。
合成线程将图层分成图块,并在光栅化线程池中将图块转换为位图。
合成线程发送绘制图块命令 DrawQuad 给浏览器进程。
浏览器进程根据 DrawQuad 消息生成页面,并显示到浏览器上。

重排、重绘和合成

重排:当页面的几何位置属性被改变时,如高度、宽度等,那么浏览器触发重新布局。
重绘:当页面只是被修改了颜色,那么布局阶段将不会被执行。
重绘省去了布局和分层的阶段,执行效率比重排操作要高。
合成:如果使用了 CSS 里面的 transform 属性来实现动画效果,它既不重排、也不重绘。而是在非主线程上执行了合成动画的效果。所以,合成能大大提升绘制效率。

减少重排重绘

  1. 使用 class 操作样式,而不是频繁操作 style
  2. 避免使用 table 布局
  3. 批量dom 操作,例如 createDocumentFragment,或者使用框架,例如 React
  4. Debounce window resize 事件
  5. 对 dom 属性的读写要分离
  6. will-change: transform 做优化

上一篇 下一篇

猜你喜欢

热点阅读