简单总结:
-
解析URL
- 分析URL中的协议(http[s]://、域名、端口等,若不是有效链接则转为搜索
-
检查缓存 浏览器判断请求资源是否在本地缓存,如果有缓存并且在缓存有效期内,直接使用缓存内容
这一步的缓存使用的是强缓存:Expires (http1.0) / Cache-Control (http1.1)
-
DNS解析 举个例子,比如用户在浏览器中输入这个域名:123.abc.qq.com.cn
- 浏览器会先看自身有没有对这个域名的缓存、如果有、就直接返回、如果没有、就去问操作系统、操作系统也会去看自己的缓存、如果有、就直接返回、如果没有、再去主机文件看、也没有、才会去问LDNS。
- LDNS会去先看看自己有没有123.abc.qq.com.cn的A记录,要有就直接返回,要没有,就去看有没有abc.qq.com.cn的NS记录,如果有,就去问它要答案,如果没有,就去看有无qq.com.cn的NS的记录,如果有,就去问它,没有就去看有无com.cn的DNS,还没有就去看有无cn的DNS,如果连cn的NS记录都没有,才去问根。
只有在各处都没有缓存的时候,我们才会问根。
优化:
- dns-prefetch
<link rel="dns-prefetch" href="//g.alicdn.com"/>
注:dns-prefetch需慎用,多页面重复DNS预解析会增加重复DNS查询次数。
- dns负载均衡
-
建立TCP连接
ACK(确认标志) 与 ack(确认号字段) 需要区分开
三次握手:
- 客户端发送一个标志位 SYN = 1、序列号 seq = x 的数据包,客户端进入 SYN_SEND 状态,等待服务端确认
- 标志位 SYN 表示要建立连接
- 序列号 seq = x 表示向接收端发送的数据
- 服务端收到 SYN 包,必须确认客户的 SYN(ack=x+1),同时自己也发送一个
标志位 SYN = 1、标志位 ACK = 1、序列号 seq = y 、确认号 ack = x + 1
的数据包,服务端进入 SYN_RCVD 状态- 标志位 SYN 表示要建立连接
- 标志位 ACK 表示收到了请求
- 序列号 seq = y 表示向接收端发送的数据
- 确认号 ack = x + 1 表示上一次握手发来的序列号 seq 的值 + 1
- 客户端发送一个标志位为
标志位 ACK = 1、确认号 ack = y + 1 、序列号 seq = x + 1
的数据包- 标志位 ACK 表示收到请求
- 序列号 seq = x + 1 表示上一次握手发来的 ack 的值
- 确认号 ack = y + 1 表示上一次握手发来的序列号 seq 的值 + 1
四次挥手:
- 客户端发送一个标志位 FIN、序列号 seq = x 的数据包,客户端进入 FIN_WAIT_1 状态
- 标志位 FIN 表示要释放连接
- 服务端防止还有数据没有传输完成,所以并没有发送标志位为 FIN 的释放连接数据包,而是先发送了一个确认收到的应答数据包
标志位 ACK = 1、序列号 seq = y、确认号 ack = x + 1
。发送后,服务端进入 CLOSE_WAIT 状态。也就是告诉客户端:请求已经收到,但是我还没有准备好,请继续等待我释放连接的消息。当客户端收到之后,客户端进入 FIN_WAIT_2 状态。- 标志位 ACK 表示收到了请求,应答上次连接
- 服务端确认数据已经传输完成,向客服端发送
标志位 FIN = 1、标志位 ACK = 1、序列号 seq = z、确认号 ack = x + 1
的数据包,告诉客户端:服务器这边数据传输完成,已经准备好关闭连接了。服务端发送之后进入 LAST_ACK 状态。- 标志位 FIN 表示释放连接
- 标志位 ACK 表示收到了请求,应答上次连接
- 客户端收到服务器发起的第三次挥手之后,已经知道可以关闭连接了,同时它需要应答服务端的最后一次确认,所以会向服务器发送
标志位 ACK、序列号 seq = x + 1、确认号 ack = z + 1
的数据包。发送成功后客户端进入 TIME_WAIT 状态。服务端收到后正式服务端正式断开连接,进入 CLOSED 状态。同时客户端在发送之后等待 2MSL 后依然没有收到回复则证明服务端已正常关闭,客户端随即也断开连接进入 CLOSED 状态。
- 客户端发送一个标志位 SYN = 1、序列号 seq = x 的数据包,客户端进入 SYN_SEND 状态,等待服务端确认
-
发送HTTP请求
-
服务器处理请求并返回 HTTP 报文
-
浏览器解析渲染页面
js变量提升
所谓的变量提升,是指在JavaScript代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。
js闭包
-
从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
-
从实践角度:以下函数才算是闭包:即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)在代码中引用了自由变量
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
闭包的用途:
-
可以读取函数内部的变量
-
让这些变量的值始终保持在内存中
-
把一些函数内的值保存下来,闭包可以实现方法和属性的私有化
使用闭包的注意点:
-
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
-
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
浏览器渲染过程
-
解析html建立dom树
-
解析css构建render树(将CSS代码解析成树形的数据结构,然后结合DOM合并成render树)
-
布局render树(Layout/reflow),负责各元素尺寸、位置的计算
-
绘制render树(paint),绘制页面像素信息
-
浏览器会将各层的信息发送给GPU(GPU进程:最多一个,用于3D绘制等),GPU会将各层合成(composite),显示在屏幕上。
vue双向绑定与响应式原理
双向绑定:
响应式:
Vue 采用的是数据劫持结合发布和-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
EventLoop
宏任务:
- script(整体代码)
- setTimeout/setInterval
- I/O
- UI 渲染
- postMessage
- MessageChannel
- requestAnimationFrame
- setImmediate(Node.js 环境)
微任务:
- new Promise().then()
- MutaionObserver
- process.nextTick(Node.js 环境)
HTTP/1.1
-
长连接:引入了 TCP 连接复用,即一个 TCP 默认不关闭,可以被多个请求复用
-
管道机制:在一个TCP连接内,多个HTTP请求可以并行,客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务端必须按照接收到客户端请求的先后顺序依次响应,以保证客户端能够区分出每次请求的响应内容。
部分解决了队头阻塞(如果前一个请求如果很耗时,那么后面的请求即使服务器已经处理完成,仍要等待前面的请求处理完才开始按序返回)
HTTP/2
-
多路复用:同一个TCP连接里面,客户端和服务器可以同时发送多个请求和多个响应,并且不用按照顺序来。由于服务器不用按顺序来处理响应,所以避免了“对头堵塞”的问题。
在 HTTP 2.0 中,有两个非常重要的概念,分别是帧(frame)和流(stream)
帧代表最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流
多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这种技术,可以避免 HTTP 旧版本中的对头阻塞问题,极大的提高传输性能
-
二进制协议:HTTP/1.1版本的头部信息是文本,数据部分可以是文本也可以是二进制。HTTP/2版本的头部和数据部分都是二进制,且统称为‘帧’
-
Header压缩:在 HTTP 1.x 中,我们使用文本的形式传输 header,在 header 携带 cookie 的情况下,可能每次都需要重复传输几百到几千的字节。
在 HTTP 2.0 中,使用了 HPACK 压缩格式对传输的 header 进行编码,减少了 header 的大小。并在两端维护了索引表,用于记录出现过的 header,后面在传输过程中就可以传输已经记录过的 header 的键名,对端收到数据后就可以通过键名找到对应的值。
-
服务端Push:在 HTTP 2.0 中,服务端可以在客户端某个请求后,主动推送其他资源。
队头阻塞:
HTTP/1.1 使用持久连接时,一个连接中同一时刻只能处理一个请求。当前的请求没有结束之前,其他的请求只能处于阻塞状态。
Angular、Vue、React
区别
-
模板 vs JSX:React与Vue,angular最大的不同是模板的编写。Vue和angulr鼓励你去写近似常规HTML的模板。写起来很接近标准HTML元素,只是多了一些属性。而react则崇尚all in js 所以独创jsx的编写风格,但是他们本质上都是一个语法糖,编译之后都是一个可执行的函数。
-
Virtual DOM vs Incremental DOM:在底层渲染方面,vue 和react 都使用的虚拟dom,而angular 却没有使用,使用的是Incremental DOM
什么是Vue的渐进式
Vue的渐进式是指Vue框架的设计理念,它允许开发者逐步采用Vue的特性和功能来构建应用程序。这意味着你可以选择只使用Vue的核心库来进行简单的交互,也可以结合Vue的路由、状态管理和其他插件来构建更复杂的应用。
渐进式的Vue框架有什么优势
-
灵活性:Vue的渐进式设计使得开发者可以根据项目的需求选择合适的功能和插件,避免了不必要的复杂性和冗余代码。
-
学习曲线低:对于初学者来说,可以先学习Vue的核心库,逐渐掌握其基本概念和用法。然后再根据需要深入学习和应用Vue的其他特性和插件。
-
性能优化:渐进式设计使得Vue可以按需加载和优化,减少了不必要的资源消耗,提升了应用程序的性能。