从输入url到浏览器渲染都经历了什么?前端想知道的都有

70 阅读7分钟

作为前端,我们需要了解到的包括:

  1. 浏览器的进程是如何工作的?
  2. 强缓存和协商缓存是如何工作的?
  3. 请求时如何进行的?
  4. 页面如何渲染的?

那么看到这一篇就能知道整体是如何工作的

输入的过程

从输入这个动作开始就进入了浏览器进程:
    
    输入的网址url包括协议、主机、端口、路径、查询参数、锚点等构成一个http请求;
    首先我们根据请求头中的强缓冲机制(exprises和cache-contorl)判断是否击中缓冲,如果没有命中继续;
    根据请求头中协商缓存机制(if-modified-since和if-none-match)判断是否命中;如果没有命中继续;
    这里如果协商缓冲命中,就需要判断Etag可能还要判断Last-Modified,来判断是否对服务器发起请求或直接用缓存;

这里就包括处理缓冲标识:
强缓存:向浏览器缓存查找请求结果,通用首部字段中的cache-control(控制缓冲行为:例如设置max-age,同Expires很像,但优先级高;public等),响应头中Expires:会将资源失效的日期告知客户端;
协商缓存:
1、判断响应头中的ETag,文件内容有变动时服务端会改变响应头中的ETag的值,客户端接受到Etag值后,在下次请求时,请求头中的if-none-match的值就是Etag的值,发送给服务端。如没有Etag则继续2
2、判断响应头中的Last-Modified,请求头中的If-Modified-Since就是Last-Modified的值(资源最后修改时间,第一次请求时响应头会加上)发送给服务端。服务端拿到if-none-match或If-Modified-Since会做比较修改相对于的响应头的值。

发起请求前

发起http请求之前,我们需要获取像访问网页的IP地址,浏览器会发一个UDP(用户数据报协议)的包给DNS协议去解析服务器.这里其实就是发送域名给DNS协议;
DNS协议通过递归方法从浏览器缓冲、系统缓存和路由器中查询,或者通过迭代的方式询问各级服务的方式查找;同时DNS还有负载均衡,一个域名对应多个服务器ip地址,当使用负载均衡还有可以进行DNS预解析;这样我们就找到了要访问的IP地址;

发起请求

浏览器进程发送url请求给网络进程:
接下来建立连接:提到网络分层,http协议及DNS协议是在应用层,网络请求和返回的过程中,会有TCP这个传输通道进行连接,这就是传输层,请求时先进行三次;
第一次挥手当然是浏览器发起的,告诉服务器我要发请求了,第二次挥手服务器发起,告诉浏览器,我知道了,可以发,第三次挥手浏览器发起,收到你的回信,那我就正式发送请求了(这次可以带上数据发送);

如果是https协议,相当于http+ssl/tcl协议;
但多加4次握手:
第一次客户端发送client hello消息和协议版本,加密算法,压缩算法随机数等给服务器;
第二次服务器收到了消息后对应携带的数据返回同样的内容,同时还会返回服务端的证书链certificate、serverKeyExchange公钥和签名、可能也发已经验证客户端的证书了、以及告诉客户端证书我是否都传了;
第三次客户端收到了服务的信息后,会对公钥加密成随机字符串、通知服务端后面的数据会加密,以及告诉服务端可以结束了;
第四次服务端收到信息后回复客户端后面的数据我也会加密的,那就结束吧;
完成了TCL的4次握手。

回到发送http请求了,http协议是无状态、无连接、灵活、支持客户端和服务端交互的,简单快速超文本传输协议;此时http协议生成请求报文,这时TCP协议就会把请求报文分割成报文段,传给解析出来的服务器,此时IP协议,会处理数据包,一边传送一边中转,

响应请求

之后服务器接收到了请求头等数据后会处理请求,常见的处理web请求的应用包括apache、nginx、lighttpd或IIS等,静态资源直接去服务器取,动态资源需要运行脚本处理,生产结果,

作为响应发送给客户端,这就是http响应报文,仍然是TCP协议会把响应报文分割成报文段,传给客户端。网络进程解析后,转发给浏览器进程。

浏览器渲染

浏览器进程接收到响应头数据后,发送commitNavigation消息(包括响应数据)给渲染进程,渲染进程收到数据和网络进程建立数据管道,之后给浏览器进程提交确认,浏览器进程确认文档提交后,网路进程的响应体进入渲染进程中的GUI线程,分以下几步:
1html转换成DOM树
2、css转换成CSSOM树
3、DOM树和CSSOM树合并形成渲染树;
4、就开始渲染了,获取DOM后分割多个图层;
5、对每个图层的节点计算样式结果;
6、对每个节点进行重排,就是生成图形和位置,和大小、尺寸、增删有关系;之后一定重绘;
想要减少重排:css避免多层内联样式&css表达式&table、动画应用到position:absolute/fixed上、直接改变最末端class;
            js避免频繁修改样式和操作DOM、可以通过displaynone不会引发重排重绘;
7、对每个节点进行重绘,就是讲样式填充到图层位中;不一定需要重排;
8、图层作为纹理上传到GPU、图层重组生产最终屏幕图像;
最后浏览器进程更新页面状态。

与此同时,浏览器会进行缓存,可以根据上文中“处理缓冲标识”对照一下。

断开连接

之后就断开连接:TCP四次挥手
1、客户端发送关闭请求的报文(指定一个序列号)给服务端,客户端就处在等待关闭的状态里了;
2、服务端收到了消息,发送确认报文(原序列号值+1),回复客户端,我也会进入等待关闭状态了;
3、此时服务端也确定要关了,发送关闭报文(指定一个序列号)给你客户端,请求关闭,同时客户端也到了即将关闭的状态了;
4、客户端收到了服务端的关闭报文,发送给服务端同步报文,客户端会等2MSL后就自动关闭了。

这里补充一下浏览器是多进程的

包括渲染进程、browser主进程、插件进程、GPU进程、网络进程;
浏览器内核是渲染进程(包括五个线程)
GUI线程:上文我已经补充了;
js引擎线程、
事件触发线程、
异步http请求线程、
定时触发线程、
存储线程。

下一篇会继续介绍作为前端,咱们前端打包的文件有js脚本、css脚本、html脚本;那么在浏览器中分别会存放在什么地方呢?或者前端缓存到底是什么?

敬请期待,欢迎讨论!