浏览器中输入 url 到底发生了什么
首先解释 url 是什么。
URL
访问协议 + 域名(服务器名称地址)+ 请求文件(资源)路径名
有了域名就可以进行一个 DNS 查询
DNS(域名系统,domain name system)
域名系统产生:服务器一般都有一个 IP,而这个 IP 地址很难记住(168.127.4.xxxx)。如果使用域名就很好记了(bing.com)。
DNS 主要是将 IP 和域名进行一个映射,通过域名找到对应的 IP 的服务器,然后去找到正确的资源。
所以用户再输入 url 后,会去查找 dns。
DNS 查找顺序
- 首先去浏览器的 dns 缓存 中查找;
- 如果没有命中就去操作系统中 dns 缓存中找;
- 如果没有命中,去本地 hosts 文件查找;
hosts 文件:定义了一个映射关系,也就是一个 IP 地址和一个与之有映射关系的主机名。
- 如果没有命中,操作系统会向域名服务器发送请求(递归查找);
- 首先查找本地 dns 服务器;
- 如果没有找到,会向根域名服务器查找(.);
- 如果没有找到,会向顶级域名服务器查找(com.);
- 如果没有找到,会向权威域名服务器查找(baidu.com.);但是如果配置了 CDN,dns 会将最终的域名解释权通过获取对应的 cname 域名交给 cdn 专用的 dns 服务器。
通过 dns 查询到了对应的 IP 地址之后,就可以向它发送网络请求了。
发送请求前会通过传输层 TCP/IP 进行三次握手,保证数据传输的可靠,然后就可以发送 HTTP 请求了。
HTTP 的 options 预检请求
浏览器在发送一个跨域的 HTTP 的 post 请求时,通常会发送一个 options 的请求:这个 OPTIONS 请求被称为预检请求(pre-flightrequest),用于确定接收请求的服务端能否进行正常通讯(浏览器有可能已经缓存了这个预检请求导致不发送);预检请求发送条件:
- 请求头 Content-Type 设置 application/json;
- 用户自定义了请求头;
浏览器缓存
浏览器的缓存分为强缓存和协商缓存;
强缓存
让浏览器强制缓存服务端提供的资源。一般是用于静态资源的缓存(css 等)。
该缓存可以通过后端配置
Expires或Cache-Control max-age=10。
这样浏览器在第二次请求这个资源时就不需要经过服务端了,直接从缓存中读取。
存储位置有硬盘缓存和内存缓存。浏览器多次读取缓存时可能会直接从内存缓存中读取,第一次都是从硬盘缓存中读取。
协商缓存
浏览器跟后端协商进行缓存。
通过对比 last-modified 和 if-modified-since(GMT 时间),etag 和 if-none-match(任意形式)来判断该资源是否被改动过。
如果发现该资源没有变动,服务端则会返回 304,表示资源没有改变,并且响应体为空。浏览器拿到后,就知道原本可能过期的缓存其实还可以继续使用。如果资源改变了,就会返回 200,且响应体带上最新资源。
浏览器缓存完成后,就进行 TCP 的四次挥手了断开连接了。此时浏览器已经拿到了对应的 html 资源准备开始渲染。
浏览器渲染页面
浏览器将 html 里的标签解析成一个 dom 树(抽象语法树);
浏览器的渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算出 DOM 节点的样式,该过程会处理样式的继承和层叠,属性值标准化,被称为 cssom;
css 样式的来源主要有三种:link 外部引入的 css、style 标签内的 css、内联 css。
浏览器渲染时肯定会触发回流和重绘。
回流
当渲染树中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部 document 的过程称为回流。
能够引起回流的操作:
- 页面首次渲染
- 浏览器窗口大小发生变换
- 元素尺寸或位置发生改变
- 元素内容发生改变
- 元素字体大小变换
- 添加或删除可见的 dom 元素
- 激活 css 伪类(:hover)
- 查询某些属性或调用某些方法
clientwidth、clientHeight 、clientTop、clientLeftoffsetwidth 、offsetHeight 、offsetTop 等
重绘
当页面中元素样式的改变并不影响它在文档流中的位置时,浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
然后浏览器通过 v8 引擎(c++编写)解析 js。
浏览器解析 js
涉及编译原理一些内容。
通过解析器将我们输入的代码变成抽象语法树,然后再转换为中间代码(字节码),再由解释器将字节码解析成机器码。
中间代码的存在是为了兼容不同的操作系统,让我们的代码具有跨平台执行的功能。
v8 使用的是 jit 解析器,即即时编译,边解析边执行;(中间有一个监视器去寻找后续需要解析的代码)
还有 AOT 解析器,直接编译成二进制文件,苹果里用的很多。
通过解释器解释后的机器码(0101)就到了 CPU 中。开始进入计算机组成原理部分,输入设备-> 存储器 -> 输出设备