在浏览器地址栏输入url到按下回车发生了什么?
来源 | https://juejin.cn/post/6896844956284125191
详解
解析url
DNS解析
浏览器会先检查是否存在缓存,因为如果访问过一次该域名的话,会把结果缓存在浏览器中。
操作系统也会有自己的DNS缓存,但在这之前,会检查域名是否存在于本地的Hosts文件中。
路由器中也会有自己的缓存。
IPS DNS缓存 就是在客户端电脑上设置的首选DNS服务器。
在前边所有的情况下都没有找到缓存的情况下,会连接互联网,把请求转发到互联网的根域。
TCP连接
发送方:发送消息,等待...
接收方:接收消息,并给发送方回信,此时发送方接收到消息后,从发送方的角度就可明白自己的消息是可以发过去的。但是接收方还不能确定自己的消息是否可以正常发送。
发送方:接收到发送方的回信后,在给接收方发一个消息,此时从接收方的角度就能明白自己的消息可以可以正常发送。
发送http请求
请求路径
查询参数
请求方法
请求头
请求体
服务器接收请求
const http = require('http'); // 引入http模块
const server = http.createServer((req, res) => {
// req保存了浏览器携带的信息
// 解析出req的相关信息,比如 路径 请求方法 请求头 请求体等
// 编写服务端逻辑处理代码
// 响应
res.end();
})
server.listen(3000, () => console.log('::3000'));
// 假设该程序巡行在 ip地址为 140.143.201.230的服务器上
// 假设 140.143.201.230 绑定的域名是 www.aabbcc.com
// 那么请求地址 可以为 http://www.aabbcc.com:3000/home
// 当浏览器请求 http://www.aabbcc.com:3000/home之后,会DNS解析到服务器的ip地址为140.143.201.230,那么上述http.createServer接收的回调函数就会执行。
服务器响应
状态码
状态文本
响应头
响应体
TCP链接断开
浏览器端发消息通知服务器现在需要断开(第一次挥手)
服务器接到要断开的请求之后,给浏览器返回消息,告诉浏览器我正在准备释放(第二次挥手)
此时浏览器接到消息后正在等待服务器释放完成,而服务器正在准备释放的过程
当服务器释放完成后,再通知浏览器我已经释放完成了。(第三次挥手)
浏览器接收到服务器释放完成的消息后,再给服务器发送消息告诉服务器我已经知道你释放完成了,服务器收到消息后,就能确认自己释放完成的消息已经通知到了(第四次挥手)
浏览器解析资源
首先,查看Response Header,根据响应头的指示做不同的事情,比如重定向,存储cookie,解压gzip,缓存资源等等。
接下来获取MIME类型(查看响应头的 Content-Type的值),根据不同的资源类型采用不同的解析方式
渲染页面
html页面的加载
解码:传输回来的其实都是一些二进制字节数据,浏览器需要根据文件指定编码(例如UTF-8)转换成字符串,也就是HTML 代码 预解析:预解析做的事情是提前加载资源,减少处理时间,它会识别一些会请求资源的属性,比如img标签的src属性,并将这个请求加到请求队列中。 符号化:符号化是词法分析的过程,将输入解析成符号,HTML 符号包括,开始标签、结束标签、属性名和属性值。它通过一个状态机去识别符号的状态,比如遇到<,>状态都会产生变化。 构建树:在上一步符号化中,解析器获得这些标记,然后以合适的方法创建DOM对象并把这些符号插入到DOM对象中。
CSS解析
javaScript编译执行
词法分析:js脚本加载完毕后,会首先进入语法分析阶段,它首先会分析代码块的语法是否正确,不正确则抛出“语法错误”,停止执行。
预编译:js有三种运行环境分别是 全局环境,函数环境,eval。每进入一个不同的运行环境都会创建一个对应的执行上下文,根据不同的上下文环境,形成一个函数调用栈,栈底永远是全局执行上下文,栈顶则永远是当前执行上下文。
执行:js虽然是单线程的,但是实际参与工作的线程一共有四个:JS引擎线程(主),事件触发线程,定时器触发线程,HTTP异步请求线程
总结
解析url地址
DNS解析
TCP链接
发送http请求
服务器接收请求
服务器响应
TCP链接断开
浏览器解析资源