用户输入 url 并回车
浏览器进程检查 url,组装协议,构成完整的 url
浏览器进程通过进程间通信(IPC)把 url 请求发送给网络进程
网络进程接收到 url 请求后检查本地缓存是否缓存了该请求资源,如果有则将该资源返回给浏览器进程
如果没有,网络进程向 web 服务器发起 http 请求(网络请求):
- 进行 DNS 解析(浏览器缓存 -> 系统缓存 host-> 本地服务器 -> 远程服务器),获取服务器 ip 地址
- 利用 ip 地址和服务器建立 tcp 连接 (三 z 次握手) 打开端口
- 构建请求头信息
- 发送请求头信息
- 服务器响应后,网络进程接收响应头和响应信息,并解析响应内容
- 初始请求的响应包含所接收数据的第一个字节。首字节时间(TTFB)是用户通过点击链接进行请求与收到第一个 HTML 数据包之间的时间。第一个内容分块通常是 14KB 的数据。
网络进程解析响应流程;
- 检查状态码,如果是 301/302,则需要重定向,从 Location 自动中读取地址,重新进行第 4 步 (301(会读本地缓存 )307 不能更改方法 /302(不会)308 不能更改方法),如果是 200,则继续处理请求。
- 200 响应处理:检查响应类型 Content-Type ,如果是字节流类型,则将该请求提交给下载管理器,该导航流程结束,不再进行后续的渲染,如果是 html 则通知浏览器进程准备渲染进程准备进行渲染。
准备渲染进程
- 浏览器进程检查当前 url 是否和之前打开的渲染进程根域名是否相同,如果相同,则复用原来的进程,如果不同,则开启新的渲染进程
传输数据、更新状态
- 渲染进程准备好后,浏览器通过 IPC 向渲染进程发送文档的消息,渲染进程接收到消息和网络进程建立传输数据的 “管道”
- 渲染进程接收完数据后,向浏览器发送 “确认提交”
- 浏览器进程接收到确认消息后更新浏览器界面状态:安全、地址栏 url、前进后退的历史状态、更新 web 页面
- 渲染进程开始渲染
页面渲染
- 通过遍历 DOM 节点树创建一个 “Frame 树” 或 “渲染树”,并计算每个节点的各个 CSS 样式值
- 通过累加子节点的宽度,该节点的水平内边距 (padding)、边框 (border) 和外边距 (margin),自底向上的计算 "Frame 树" 中每个节点的首选 (preferred) 宽度
- 通过自顶向下的给每个节点的子节点分配可行宽度,计算每个节点的实际宽度
- 通过应用文字折行、累加子节点的高度和此节点的内边距 (padding)、边框 (border) 和外边距 (margin)
- 使用上面的计算结果构建每个节点的坐标
- 创建 layer (层) 来表示页面中的哪些部分可以成组的被绘制,而不用被重新栅格化处理。每个帧对象都被分配给一个层
- 每个层的帧对象都会被遍历,计算机执行绘图命令绘制各个层,此过程可能由 CPU 执行栅格化处理,或者直接通过 D2D/SkiaGL 在 GPU 上绘制
- 上面所有步骤都可能利用到最近一次页面渲染时计算出来的各个值,这样可以减少不少计算量
- 计算出各个层的最终位置,一组命令由 Direct3D/OpenGL 发出,GPU 命令缓冲区清空,命令传至 GPU 并异步渲染,帧被送到 Window Server。
- 浏览器输入的 url 经过 DNS 解析获得对应的 IP 地址
- 向服务器发起 TCP 的 3 次握手
- 建立链接后,浏览器向该 IP 地址发送 http 请求
- 服务器接收到请求,HMTL 格式的字符串代码
- 浏览器获得 html 代码,解析成 DOM 树,同时 js 阻塞解析
- 获取 CSS 并构建 CSSOM
- 将 DOM 与 CSSOM 结合,创建渲染树
- 找到所有内容都处于网页的哪个位置,布局渲染树
- 最终绘制出页面