常见面试题:地址栏输入url按回车发生了什么?(越详细越好)
很熟悉的标题,总结一下自己的理解,欢迎各位同行赐教!:)
总结依据webkit技术内幕和http权威指南两书
一:输入url,url的组成,有什么用?
通常最简单的url,就像这样:http://www.jianshu.com/,这串url就包含方案(就是通信协议,常见的http,https),服务器地址(www.jianshu.com),端口号(http协议默认是80端口,https协议默认是443端口,https就是加密的http协议,就是在http和TCP之间加了一层TSL或者SSL的安全层),资源(默认是index.html)。
二:通过url解析出ip地址(到了我们常说的DNS域名解析了)
1.我们来看第一次访问某个站点的时候要做什么?
如上所诉,url解析出了服务器域名,现在要将域名解析出ip地址,就要请求域名服务器来解析ip,比如www.jianshu.com.这个域名,后面多了一个点,这个点就表示公网,通常是省略的,域名解析就是从右向左开始解析,解析.域->com域->jianshu.com域->www.jianshu.com域这样就拿到ip地址(其中的查找过程也是很复杂的,这里我们只概括),如下解析过程:
用户发起请求->操作系统把域名发送给本地区的域名服务器->有就解析返回ip,然后结束;
用户发起请求->操作系统把域名发送给本地区的域名服务器->没有->到Root Server的域名服务器请求解析->返回一个主域名(.com)的服务器地址地址->本地的域名服务器再向主域名服务器发起请求->返回Name Server域名服务器地址(jianshu.com)->接下来的解析就由域名提供商的服务器来解析->Name Server域名服务器查询存储的域名和ip的映射关系表->返回ip地址和一个过期时间,根据这个时间缓存到本地,解析结束。
2.第二次再访问同样站点的时候要做什么?
通常第一次访问完成之后,浏览器会将域名解析的映射缓存到本地,下次再访问该站点的时候,会先从浏览器的缓存中查看有没有这个域名被解析过得ip地址,有没有过期等,如果有这个ip而且没有过期,解析过程就结束。如果浏览器的缓存中没有,浏览器就会查找操作系统的缓存中是否有对应域名的ip地址(操作系统的域名解析也有一个过程的,大家可以自行搜索)。
浏览器的dns缓存目录三:ip地址解析完成之后,就开始发请求
前面通过url解析出方案,端口号,域名服务器解析出ip地址,此时浏览器发起到122.228.25.221端口80的TCP连接,在建立连接之前浏览器和服务器会进行三次握手:
第一次:浏览器向服务器发送请求(SYN=1),等待服务器确认;
第二次:服务器收到请求并确认,回复一个指令(SYN=1,ACK=1);
第三次:客户端收到服务器的回复指令,并返回确认(ACK=1);
1.首先浏览器发送连接请求报文,2.服务器接受连接后回复ACK报文,并为这次连接分配资源。3.浏览器接收到ACK报文后也向服务器发生ACK报文,并分配资源,这样TCP连接就建立了,开始数据传输。浏览器向服务器发送http的请求报文,浏览器从服务器读取响应报文,然后浏览器关闭连接。
综合前两个的过程大致如下图:
从域名解析到发起请求的大致过程四:服务器返回html文档之后,浏览器的渲染引擎开始dom解析过程(构建DOM树->渲染树(Render tree)->布局render树->绘制render树)
1.通过网络请求拿到html文档之后,渲染引擎会调用html解析器开始解析html,将html的标签解析成dom树,如果遇到静态资源,link标签则去请求相应的资源,遇到script标签就会调用js引擎解释并执行(全局执行js代码的时候,dom树是禁止被访问的,因为js也可以操作dom结构,此时dom树并没有创建完成,所以js我们大都建议放在body元素之后(因为有些js执行期间可能会很耗时),这样就不会阻止其他资源的下载)。
解析dom树的过程:通过网络请求获取的html网页或资源从字节流解码成字符流,然后通过词法分析器解析成词语,之后经过语法分析器构建成节点,最后这些节点组成一颗dom树;(当dom树构建完成之后,webkit会触发DOMContentLoaded事件,jquery的dom ready源码实现也用到这个事件,当所有资源全都加载完毕之后会触发onload事件)
从资源的字节流到dom树2.dom树解析完成之后,渲染引擎调用css解释器根据css规则为每个dom树节点计算css样式信息,构建渲染树(Render tree);
render tree的过程:渲染引擎调用css解释器,根据css规则(解析外部或者内部引用额样式表),解析出样式信息,构建render tree,渲染树会忽略掉不需要被渲染的元素(display:none,head,meta...);
3.布局树(render layer)
构建render tree之后,每个元素并不知道自己的大小颜色等样式和位置信息,渲染引擎根据包含块和盒模型来计算元素的大小位置等信息,这就是布局计算(排版)。布局计算是一个递归过程:一个节点的大小要根据子节点的位置大小来计算,一旦布局发生变化,就要重新绘制,渲染效率就会降低,通常网页性能瓶颈大都是频繁的dom操作造成的,现在react框架的diff算法,建立虚拟dom对比上一次的dom,只绘制发生改变的那部分,大大提升性能。
4.绘制render树
渲染引擎开始绘制图像(绘制这部分很复杂,不说了,你猜我知道不知道!)