2020-04-16 从输入URL到页面展示,中间发生了什么?
地址栏输入URL
检查URL
浏览器的浏览器进程检查URL,组装协议,构成完整的URL,通过进程间通信IPC把URL请求发送给网络进程
发起http请求
网络进程接收到URL发起http请求
网络进程首先查找本地是否存在缓存
如果没有缓存就进行网络请求
网络请求首先进行DNS解析,DNS查过过程也存在缓存的问题,最终拿到目标服务器的ip
网络进程通过ip地址和服务器建立tcp链接
网络进程构建请求行,请求头,请求体,发起网络请求
拿到响应后
浏览器根据相应的状态吗判断是否进行重定向
浏览器根据相应的content-type决定如何显示相应的内容
如果是text/html,浏览器为每个页面分配一个渲染进程,如果属于same-site(根域名和协议完全一致就属于same-site),就在同一渲染进程进行渲染。
渲染进程准备好之后浏览器进程发出提交文档指令,这里的文档指的是响应体数据,渲染进程收到指令后建立和网络进程的数据管道
等文档数据传输完成后,渲染进程返回确认提交的消息给浏览器进程
浏览器进程收到确认提交消息后,更新浏览器的界面,包括前进后退的历史状态,安全状态,地址栏的URL,和正真的web页面
文档提交后渲染进程开始页面解析和子资源加载
构建dom树
渲染进程根据html构建存在内存中的dom树,document就是
样式计算
将link的外部资源,style标签内css,内联样式合并为浏览器可以理解的结构styleSheets
转换样式表中的属性值,尺寸单位统一为px,颜色为rgb等
根据css的继承规则和层叠规则计算dom树种每个节点的具体样式,保存在ComputedStyle中
布局阶段
渲染引擎创建布局树,将不可见的元素忽略掉
计算每个节点的位置,计算后重新写回布局树(这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开来,针对这个问题,Chrome 团队正在重构布局代码,下一代布局系统叫 LayoutNG,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单),对布局树进行分层,形成分层树
合成阶段
成线程会判断是否在视口附近,命令GPU将视口附进的图块转换为位图,GPU中的光栅化线程池将所有的图块光栅化(就是将图块转化成位图),保存在GPU的内存中,光栅化完成后合成线程将发送绘制命令DrawQuad给浏览器进程,浏览器进程根据DrawQuad消息生成页面,显示到显示器上。
页面完成
页面生成完成后,渲染进程发送消息给浏览器进程,收到后会停止标签栏上图标的加载动画
over
优化
渲染进程的主线程按照顺序首先构建dom树,样式计算,布局,绘制
如果发生重排(比如改变元素大小等)会直接从样式计算开始从新执行,如果发生重绘(例如改变颜色)会直接从绘制阶段开始从新执行,所以频繁的占用渲染进程的主进程,就会产生较大的开销。所以在性能优化中,减少重排和重绘的属性,渲染引擎将跳过布局和绘制,只执行非主线程的合成,例如:CSS的transform就避开重排和重绘,直接在非主线程上执行合成操作,没有占用主线程资源,所以效率最高