URL
到页面渲染的过程从输入URL
到页面渲染须要Chrome
浏览器的多个进程配合,因此咱们先来谈谈现阶段Chrome
浏览器的多进程架构。css
Chrome
架构目前Chrome
采用的是多进程的架构模式,可分为主要的五类进程,分别是:浏览器(Browser
)主进程、 GPU
进程、网络(NetWork
)进程、多个渲染进程和多个插件进程;html
HTML
、CSS
和 JavaScript
转换为用户能够与之交互的网页,排版引擎Blink
和JavaScript
引擎V8
都是运行在该进程中,默认状况下,Chrome
会为每一个Tab
标签建立一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。GPU
进程。其实,Chrome
刚开始发布的时候是没有GPU
进程的。而GPU
的使用初衷是为了实现3D CSS
的效果,只是随后网页、Chrome
的UI
界面都选择采用GPU
来绘制,这使得GPU
成为浏览器广泛的需求。最后,Chrome
在其多进程架构上也引入了GPU
进程。了解了Chrome
的多进程架构,就可以从宏观上理解从输入URL
到页面渲染的过程了,这个过程主要分为导航阶段和渲染阶段。webpack
URL
url
,组装协议,构成完整的url
,这时候有两种状况:
URL
。URL
:地址栏会根据规则,给这段内容加上协议,合成为完整的URL
;IPC
)把url
请求发送给网络进程;URL
请求过程url
请求后检查本地缓存是否缓存了该请求资源,若是有则将该资源返回给浏览器进程;这里涉及到浏览器与HTTP协议的缓存策略问题,有兴趣的能够看这篇文章:详解HTTP协议web
四、准备IP
地址和端口:进行DNS
解析时先查找缓存,没有再使用DNS
服务器解析,查找顺序为:chrome
hosts
文件;ISP DNS
缓存;DNS
递归查询(本地DNS
服务器 -> 权限DNS
服务器 -> 顶级DNS
服务器 -> 13
台根DNS
服务器)五、等待TCP
队列:浏览器会为每一个域名最多维护6
个TCP
链接,若是发起一个HTTP
请求时,这 6
个 TCP
链接都处于忙碌状态,那么这个请求就会处于排队状态;解决方案:浏览器
CDN
)域名下面。HTTP2
,就没有6
个TCP
链接的限制了;六、经过三次握手创建TCP
链接:缓存
TCP
首部中:标志位:同步SYN
为1
,表示这是一个请求创建链接的数据包;序号Seq=x
,x
为所传送数据的第一个字节的序号,随后进入SYN-SENT
状态;标志位值为
1
表示该标志位有效。安全
SYN
标志位判断为创建链接的请求,随后返回一个确认数据包,其中标志位SYN=1
,ACK=1
,序号seq=y
,确认号ack=x + 1
表示收到了客户端传输过来的x
字节数据,并但愿下次从x+1
个字节开始传,并进入SYN-RCVD
状态;这里要区分标志位
ACK
和确认号ack
;服务器
ACK=1
,序号seq=x+1
,确认号ack=y+1
,随后进入ESTABLISHED
状态;服务器端收到后,也进入ESTABLISHED
状态,由此成功创建了TCP
链接,能够开始数据传送;网络
若是没有最后一个数据包确认(第三次握手),
A
先发出一个创建链接的请求数据包,因为网络缘由绕远路了。A
通过设定的超时时间后还未收到B
的确认数据包。因而发出第二个创建链接的请求数据包,此次网路通畅,
B
的确认数据包也很快就到达A
。因而A
与B
开始传输数据;过了一会
A
第一次发出的创建链接的请求数据包到达了B
,B
觉得是再次创建链接,因此又发出一个确认数据包。因为A已经收到了一个确认数据包,因此会忽略B
发来的第二个确认数据包,可是B
发出确认数据包以后就要一直等待A
的回复,而A
永远也不会回复。由此形成服务器资源浪费,这种状况多了
B
计算机可能就中止响应了。
七、构建并发送HTTP
请求信息;
八、服务器端处理请求;
九、客户端处理响应,首先检查服务器响应报文的状态码:
301/302
表示服务器已更换域名须要重定向,这时网络进程会从响应头的Location
字段里面读取重定向的地址,而后再发起新的HTTP
或者HTTPS
请求,跳回第4
步。200
,就检查Content-Type
字段,值为text/html
说明是HTML
文档,是application/octet-stream
说明是文件下载;Conection
不是Keep-Alive
时,即不为TCP
长链接时,经过四次挥手断开TCP
链接:FIN=1
,序号位seq=u
,并中止发送数据;ACK=1
,序号seq=v
,确认号ack=u+1
的数据包;FIN=1
,标志位ACK=1
,序号seq=w
,确认号ack=u+1
;ACK=1
,序号seq=u+1
,确认号ack=w+1
的数据包。由此经过四次挥手断开TCP
链接。
详细过程参见:详解TCP链接的“三次握手”与“四次挥手”(上)
FIN
释放链接报文与ACK
确认接收报文须要分两次传输,即第二次和第三次"挥手";url
是否与以前打开了渲染进程的页面的根域名相同,若是相同,则复用原来的进程,若是不一样,则开启新的渲染进程;url
、前进后退的历史状态、更新web
页面在渲染阶段经过渲染流水线在渲染进程的主线程和合成线程配合下,完成页面的渲染;
渲染进程中的主线程部分
DOM
树1三、先将请求回来的数据解压,随后HTML
解析器将其中的HTML
字节流经过分词器拆分为一个个Token
,而后生成节点Node
,最后解析成浏览器识别的DOM
树结构。
能够经过Chrome
调试工具的Console
选项打开控制台输入document
查看DOM
树;
渲染引擎还有一个安全检查模块叫
XSSAuditor
,是用来检测词法安全的。在分词器解析出来Token
以后,它会检测这些模块是否安全,好比是否引用了外部脚本,是否符合CSP
规范,是否存在跨站点请求等。若是出现不符合规范的内容,XSSAuditor
会对该脚本或者下载任务进行拦截。
首次解析HTML
时渲染进程会开启一个预解析线程,遇到HTML
文档中内嵌的JavaScript
和CSS
外部引用就会同步提早下载这些文件,下载时间以最后下载完的文件为准。
CSSOM
1四、CSS
解析器将CSS
转换为浏览器能识别的styleSheets
也就是CSSOM
:能够经过控制台输入document.styleSheets
查看;
这里要考虑一下阻塞的问题,因为JavaScript
有修改CSS
和HTML
的能力,因此,须要先等到 CSS
文件下载完成并生成 CSSOM
,而后再执行 JavaScript
脚本,最后再继续构建 DOM
。因为这种阻塞,致使了解析白屏;
优化方案:
- 移除
js
和css
的文件下载:经过内联JavaScript
、内联CSS
;- 尽可能减小文件大小:如经过
webpack
等工具移除没必要要的注释,并压缩js
文件;- 将不进行
DOM
操做或CSS
样式修改的JavaScript
标记上sync
或者defer
异步引入;- 使用媒体查询属性:将大的
CSS
文件拆分红多个不一样用途的CSS
文件,只有在特定的场景下才会加载特定的CSS
文件。
能够经过浏览器调试工具的Network
面板中的DOMContentLoaded
查看最后生成DOM
树所需的时间;
em
转换为px
,color
转换为rgb
;DOM
树中每一个节点的具体样式,这里遵循CSS
的继承和层叠规则;能够经过Chrome
调试工具的Elements
选项的Computed
查看某一标签的最终样式;1七、建立布局树,遍历DOM
树中的全部节点,去掉全部隐藏的节点(好比head
,添加了display:none
的节点),只在布局树中保留可见的节点。
1八、计算布局树中节点的坐标位置(较复杂,这里不展开);
Layer Tree
),能够经过Chrome
调试工具的Layer
选项查看。分层树中每个节点都直接或间接的属于一个图层(若是一个节点没有对应的层,那么这个节点就从属于父节点的图层)渲染进程中的合成线程部分
2一、合成线程将图层切分红大小固定的图块(256x256
或者512x512
)而后优先绘制靠近视口的图块,这样就能够大大加速页面的显示速度;
GPU
进程GPU
来加速生成,使用GPU
生成位图的过程叫快速栅格化,或者GPU
栅格化,生成的位图被保存在GPU
内存中。DrawQuad
”,而后将该命令提交给浏览器进程。注意了:合成的过程是在渲染进程的合成线程中完成的,不会影响到渲染进程的主线程执行;
viz
的组件,用来接收合成线程发过来的DrawQuad
命令,而后根据DrawQuad
命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。到这里,通过这一系列的阶段,编写好的HTML
、CSS
、JavaScript
等文件,通过浏览器就会显示出漂亮的页面了。
参考资料:浏览器工做原理与实践