这是一道常见的面试题,下面就来说一下:
1.首先是dns的域名解析,浏览器会先查找自身的缓存记录,看有没有和url对应的ip地址,如果有返回,如果没有或者已经过期,则会去hosts文件中找,widows是在在C:\Windows\System32\drivers\etc下面,操作系统缓存可以通过ipconfig/displaydns命令查看。如果操作系统或者hosts文件都没有记录或者记录已经过期,则会向本地域名服务器发送dns请求。服务器首先会查找自身的缓存记录,如果有则返回,如果没有则向根域名服务器发起请求,根域名服务器返回可能保存了该域名的一级域名服务地址,本地主机再根据返回的地址去请求一级域名服务地址,这样一直迭代,直到找到ip地址为止
2.接下来是tcp的三次握手
第一次握手:客户端向服务器发送请求报文syn包,报文首部生成seq序列号为x,这时状态为syn-sent阶段
第二次握手:服务器接收到syn包以后生成一个ack为x+1,同时服务器也生成一个syn包,seq序列号为y,并把syn+ack包发送给客户端,此时状态为syn-recv阶段
第三次握手:客户端收到服务器的syn-ack包以后,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入established阶段,完成三次握手
3.浏览器向服务器发送http请求,请求包含请求的方法即GET,客户端的信息,请求的url,长链接等等。客户端如果请求的是静态资源,服务器会根据url地址到服务器对应的路径下查找文件,然后返回客户端一个http响应,包括状态行,响应头,响应正文等。如果是动态资源,则服务器会调用cgi/vm执行程序,比如查询数据库,返回查询结果数据集,然后将运行结果--html文件返回给web服务器,服务器再返回给客户端
4.客户端拿到文件以后会开始进行解析。
这里先介绍一下浏览器的构成,主要有界面控件(就是浏览器上面的前进后退按钮等),浏览器引擎,渲染进程,js解释器,ui后端,网络,和数据存储持久层。其中渲染进程还包括主线程,工作线程,合成线程及光栅化线程。
首先是解析html,生成dom树,因为浏览器无法直接理解和使用html文件,所以要解析成dom树,网页中经常含有图片,css,js等资源,在构建dom树的时候主线程会去请求他们。在遇到script标签时会停止dom解析,这也是为什么script标签要写到html下面的原因,js解释器和渲染进程是互斥的,如果要把script写在html上面,可以加上一个defer属性。
解析完html便是解析css,主进程会将css解析成浏览器可以解析的数据结构stylesheets,然后还会计算每个节点的样式,这里涉及了css的继承规则,有些属性会被继承,有些不会。
css解析完之后会和html合并生成布局树,布局树只会包含可见的节点,有了布局树,主线程会计算每个元素的位置信息及盒子大小。计算完节点的位置以后,主线程会对元素进行分层,得到一个分层树,拥有层叠上下文属性的会单独生成一个图层(如z-index),需要裁剪的地方也会生成一个图层等。然后是绘制图层,主线程会把图层的绘制拆分成许多个指令,生成绘制列表。主线程会将绘制列表发送给合成线程,由合成线程来完成最后的绘制,合成线程将图层划分为图块,再将图块转为位图。最后合成线程会收集位图信息来创建合成帧,合成帧随后会通过 IPC 协议将消息传给浏览器主进程。浏览器主进程收到消息后,会将页面内容绘制到内存中,最后再将内存显示在屏幕上。