浏览器输入url后都做了什么事情
博主还年轻的时候,面试都是这么回答的:
首先找到域名和ip的对应关系,本地host文件照看有没有,有就直接用,没有就去本地DNS服务器查询,本地有就直接用,没有再像根DNS服务器查询,返回对应关系后保存,这时返回的资源浏览器就可以加载了。
现在看来是如此的简单…
细说一下
平时浏览网页可能感受不到,其实这个过程还是蛮复杂的,主要就是这几个过程。
- 输入地址
- 浏览器查找域名的 IP 地址
- 浏览器向 web 服务器发送一个 HTTP 请求
- 服务器的永久重定向响应
- 服务器处理请求
- 服务器返回一个 HTTP 响应
- 浏览器显示 HTML
- 浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等
输入地址
用户输入URL,浏览器会根据用户输入的信息判断是搜索还是网址。如果是搜索内容,就将搜索内容+默认搜索引擎合成新的URL;如果用户输入的内容符合URL规则,浏览器就会根据URL协议,对一些默认的东西进行补齐,合成合法的URL,然后进行自动完成、字符编码等操作,生成请求报文,现在的浏览器就已经在智能匹配了,比如常用的谷歌浏览器,有时候url没输入完页面都出来了,还会进行安全检查、访问限制等操作。由于安全隐患,会使用 HSTS 强制客户端使用 HTTPS 访问页面。
查浏览器缓存
- 浏览器发送请求前,根据请求头或者响应头的expires和cache-control判断是否命中(包括是否过期)强缓存策略,(expires和cache-control是根据资源第一次被请求时保存的)如果命中,直接从缓存获取资源(memory cache/disk cache),并不会发送请求。如果没有命中,则进入下一步。注意这里暂时不会与服务器交流。
- 没有命中强缓存规则,浏览器会像服务器发送请求,根据响应头的last-modified和etag判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步。
浏览器查找域名的 IP 地址
因为发送 HTTP 请求报文需要依赖下层 TCP 协议,TCP 建立连接并通信是需要 IP 地址 + 端口号 这一对二元组的,端口号可以直接从 URL 中获得,但是 IP 地址需要由 DNS 解析域名来获得。DNS 服务主要功能就是将 URL 中的域名,解析为 IP 地址。
此时如果需要发起请求的主机和被请求的主机是在一个局域网内(比如n个主机通过一个交换机链接),就需要ARP协议发挥作用,因为局域网内主机是通过MAC地址通信。
会先查看自己浏览器有没有缓存此域名的信息,如果没有则进一步查看操作系统缓存(本地host),如果有则直接返回,如果没有则准备发送 DNS 请求,没有再递归查询本地DNS服务器缓存,没有再问根DNS服务器,根DNS服务器迭代查询后提供顶级域名服务器地址,去这里查询,然后顶级域名服务器再给出一个域服务器地址查询,返回域名和ip对应关系给本地DNS,并且本地DNS缓存下这个对应关系。
发请求
- 发起TCP连接请求:用上面拿到的拿到域名和ip的对应关系,浏览器以一个随机端口像服务器80端口(http)/443端口(https)发起TCP连接请求,请求到达服务端后经过路由器、网卡等后到达内核的TCP/IP协议栈,最终到达web程序三次握手建立TCP链接。
- http请求:可能是get/post等方法,包含请求行,请求头,请求体
- 这里服务器有可能返回301、302状态码,需要重定向,这时候又要发送重定向的http请求
服务器处理请求
接受 TCP 报文后,会对连接进行处理,对HTTP协议进行解析(请求方法、域名、路径等),并且进行一些验证:
验证是否配置虚拟主机
验证虚拟主机是否接受此方法
验证该用户可以使用该方法(根据 IP 地址、身份信息等)
浏览器接收数据
浏览器接收到来自服务器的响应资源后,会对资源进行分析。
首先查看 Response header,根据不同状态码做不同的事(比如301、302重定向)。
如果响应资源进行了压缩(比如 gzip),还需要进行解压。
然后,对响应资源做缓存。
接下来,根据响应资源里的 MIME 类型去解析响应内容(比如 HTML、Image各有不同的解析方式)。
浏览器渲染
渲染引擎
- html解析
解码、预解析、符号化、构建dom树(遇到script标签会停止构建,如果js依赖css会等到css规则构建完毕才运行),浏览器还会进行纠错 - css解析
下载的css通过与法规范进行解析,尽量用class或id避免过多的查找
css权重,!important->行内样式->id->class(伪类)->标签元素(伪元素) - 渲染树
dom和css树的结合
原则:(避免html解析出现的问题)
CSS 资源排在 JavaScript 资源前面
JS 放在 HTML 最底部,也就是