以Google浏览器为例
- 用户在地址栏中输入内容
- 判断用户输入的是搜索内容还是请求的URL
- 如果是搜索内容,地址栏会使用浏览器默认的搜索引擎合成带搜索关键字的URL
- 如果是URL,地址栏会根据规则,合成带有协议的完整URL
- 判断用户输入的是搜索内容还是请求的URL
- URL请求
- 查找本地缓存是否存有该资源
- 有,直接返回缓存资源给浏览器
- 无,进入下一步网络请求流程
- DNS解析,获取请求的IP地址
- 利用IP地址和服务器建立TCP链接
- 浏览器端构建请求行、请求头信息,把cookie数据附加到请求头中,发送给服务器
- 服务器接收到信息后生成响应行、响应头、响应体,并发送给网络进程
- 网络进程接收到响应信息后进行解析
- 响应行返回状态码301或302,浏览器需要重定向到响应头Location字段的URL地址,重新开始发起请求
- 响应行返回状态码200,请求成功,进入下一步
- 响应数据类型处理
- 响应头Content-Type返回值是application/octet-stream,表示返回的数据是字节流类型,浏览器会按下载类型来处理,将请求提交给浏览器的下载管理器,请求流程结束。
- 响应头Content-Type返回值是text/html,表返回的数据是HTML格式,进入下一步
- 查找本地缓存是否存有该资源
- 准备渲染进程
- 默认情况下,每打开一个新页面,创建一个新的渲染进程
- 从一个页面打开另一个页面,且两个页面在同一站点(同样的协议和根域名)下,共用一个渲染进程
- 提交文档(响应体数据)
- 浏览器进程发出“提交文档”的消息
- 渲染进程接收到“提交文档”消息后和网络进程监理传输数据的通道
- 数据传输完成后,渲染进程返回“确认提交”的消息给浏览器进程
- 浏览器进程收到“确认提交”消息后更新浏览器的页面状态,包括安全状态、地址栏URL、前进后退的历史状态和web页面
- 渲染阶段
- 页面解析和子资源加载
- 构建DOM树(DOM是保存在内存中浏览器可以理解的树状结构,可以通过JS进行增删改查)
- 样式计算
- 把css转换为浏览器能够理解的结构——styleSheets
- 转换样式表中的属性值,使其标准化,例如:
- em、rem等单位解析成px
- 颜色设置解析为rgb格式
- bold、lighter等单次解析成对应的数值
- ...
- 计算出DOM树中每个节点的具体样式,被保存到ComputedStyle结构内
- 样式继承
- 样式层叠
- 布局,计算DOM树中可见元素的几何位置
- 创建布局树(只包含可见元素)
- 布局计算(计算每个可见元素的坐标位置)
- 分层,生成图层树
- 布局树的节点不一定有对应的图层,若没有,则从属于父节点的图层
- 有明确定位属性、透明属性、css滤镜、剪裁等地方会被创建为图层
- 图层绘制
- 把图层的绘制拆分成很多绘制指令
- 按照顺序把绘制指令组成待绘制列表,提交到合成线程
- 分块(页面很长的时候,可视区域只能看到很小的一部分,合成线程将图层划分为图块,优先处理可视区域附近的图块,可以减小开销)
- 栅格化
- 将图块转换为位图的过程
- 使用GPU来加速生成,生成的位图保存在GPU内存中
- 合成
- 所有图块栅格化后,合成线程生成一个绘制图块的命令,提交给浏览器进程
- 浏览器接收到命令后将页面内容绘制到内存中,再将内存显示在屏幕上
- 页面生成完成后,渲染进程会发送消息给浏览器进程
- 浏览器进程收到消息后,停止标签图标的loading加载动画,一个完整的页面就生成了
- 页面解析和子资源加载