浏览器进程获取到输入的url,判断是网址还是关键词,如果是关键词就使用默认的搜索引擎搜索。如果是网址,则先判断该网址是否为安全网址(各浏览器都有自己的判断标准,Chrome有一个黑名单域名?)。若可以访问,则开启网络进程。
网络进程中,浏览器通过迭代查询向本地DNS发送请求,得到url的ip地址。本地DNS先检查有无缓存,有则直接返回,无则向根域名服务器发请求,获取对应的顶级域名服务器的地址后,再向顶级域名服务器发送请求,这里顶级域名服务器可以查看自己有无缓存,若无则返回下一级权威域名服务器的地址,再向权威域名服务器发送请求,获取最终需要的IP地址,存入本地DNS中,IP地址返回给浏览器。
得到IP地址之后,还要获取目的主机的MAC地址。将IP地址与本机子网掩码相与,判断是否在同一个子网内,若在通过ARP协议获取目的主机的MAC地址,若不在将请求转发给网关,由网关代为转发,通过ARP协议获取网关的MAC地址,此时目的主机的MAC地址即为网关的MAC地址。
此时在通过TCP三次握手建立连接。为什么不能两次握手是因为如果第一次握手时,包堵塞了导致没发到,就会再发一次,建立连接。若当前连接关闭后,前面的包到了,此时就会又建立一个连接占用资源。其实三次握手主要就是确定双方都有发包收包的能力。
如果是HTTPS,则还需要TLS的四次握手。四次握手分别得到三个key,通过这三个key合成秘钥通信。关于安全证书,所有的证书都是由CA颁发的,CA用自己的私钥加密证书以及公钥,请求方拿到证书后,根据原始信息使用相同的hash算法生成一个摘要得到证书的内容,用CA的公钥对证书中的签名进行解密,将解密的摘要和生成的摘要对比就可以知道证书是否是有效的。
浏览器拿到返回的数据后,创建渲染器进程,浏览器进程通过IPC管道将文件传输给渲染器进程,开始渲染。
渲染器进程将Html解析,先通过tokeniser标记化,通过词法分析将html的标记内容分析为多个标记,如果遇到script标签将停止解析过程去加载执行js脚本,所以可以在脚本中加上async和defer属性,前者将js脚本与文档解析并行加载执行,不能保证加载顺序,后者与文档并行加载,但是等文档解析完后再执行,在DOMContentLoaded事件触发之前执行。然后根据识别后的标记构造dom树,
构建DOM树之后,获取css样式,最后主线程通过DOM树和css样式来生成最后的LayoutTree,由于一些隐藏样式,例如display:none,所以DOM树和LayoutTree并不是一一对应的。主线程再遍历LayoutTree创建一个绘制记录表,来记录每个节点的绘制顺序,然后就是将这些信息转化为像素点显示在屏幕上即栅格化。栅格化需要调用浏览器的GPU进程。这里存在重绘和回流,需要注意回流(修改像素位置或者添加删除结点都会引起回流)。
因为回流会占用主线程和js争夺资源,所以尽量避免回流(可以多实用transform或者display:none),在实现动画是可以使用requestAnimationFrame()来进行优化,此API就是在每一帧的执行时间即将用完是将分成小的js任务快执行,页面可以在每一帧开始的时候进行布局和绘制就不会卡顿。
最后TCP四次挥手断开连接。最后一次时,发送端要等大两个MSL时间保证接收端能完整关闭连接。(为什么四次,因为服务端需要告知客户端已经收到了断开请求,然后把自己的包发完了告诉客户端可以断开了。)