这是我参与「第四届青训营 」笔记创作活动的第2天
前言
全篇主要围绕“从url输入到页面加载都发生了什么”进行展开,串联许多相关知识点,方便记忆触类旁通。
讲解深度较浅,以后加深了解后会持续添加一些深度,一些新的内容,在此做记录分享的开端。有不足的错误的也希望uu们能不吝赐教鸭。
ps:篇幅较长,主要脉络可以直接查看本文的目录表。
一、输入url地址
首先是在浏览器中输入url地址
二、查找缓存
再来就是查找缓存(获取dns记录)---浏览器缓存、操作系统缓存、路由器缓存、isp缓存
“浏览器缓存”
关键词:304、浏览器的缓存机制:强缓存、协商缓存
浏览器与服务器的通信采用应答模式,即浏览器发起http请求-服务器响应请求。
详细过程是,浏览器每次发起http请求,会先在浏览器缓存中查找该请求的结果以及缓存标识,如果缓存标识存在且结果还未失效,则强缓存生效,直接返回结果;如果缓存标识存在但缓存结果失效,则强缓存失效,使用协商缓存;如果不存在缓存标识和缓存结果,强缓存失效,浏览器再次发起http请求到服务器,服务器响应其结果并返回对应的页面。
协商缓存就是,强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。协商缓存主要由两种情况:协商缓存生效返回304,协商缓存失效返回200和请求结果
三、DNS域名解析
DNS域名解析---浏览器向dns服务器发起请求
四、建立tcp连接
建立tcp连接---根据解析出的ip地址和默认80/334端口,和服务器建立tcp连接
TCP/IP如何保证数据包传输的有序可靠?
两个机制--ack回复和超时重发
TCP和UDP的区别?
关键词:是否连接、单播 多播 广播传输、可靠性、头部开销、传输速率 实时性
TCP是面向连接的。而udp是面向无连接的
TCP播传输,udp支持单播、多播、广播
TCP次握手保证了链接的可靠性,UDP接、不可靠的数据传输协议,因为通信不需要连接,对收到的数据不发送确认接收信号,发送端就不知道数据是否被正确接收。
UDP部开销比TCP据传输速率更快 意味着实时性更好
TCP连接的三次握手
第一次握手是浏览器向服务器发起握手请求syn包,第二次握手服务器发回应答ack包和自己的握手请求syn包,第三次握手浏览器发回应答ack包
TCP连接变为两次握手可不可以,第三次握手可以省去吗?
不可以,因为tcp/ip保证数据包传输的可靠有序是需要靠ack回复的。第一二次握手,只能确保浏览器端的可发送可接收能力是正常的,由于服务器端没有收到ack回复,并不能知道自己发出的包是否被接收,也不能知道自己接收包的能力是否正常。如果保证了第三次握手,服务器端就能确认自己的发送和接收能力了。
五、发起http请求
服务器响应请求并返回请求的html文件
简述http和https、两者的区别
关键词:安全性、默认端口、握手阶段、缓存开销、费用、ca证书费用、ssl证书ip域名
http是超文本连接协议,基于tcp协议,明文传输,默认端口80
https在http的基础上,加了ssl协议,密文传输增强传输内容的保密性;https协议默认端口334;握手时间相较于http更长 会使页面加载时长延长 且更费电;https的缓存开销更大;ssl需要绑定ip,所以https需要购买域名花费,还需要购买ca证书,安全等级越好的ca证书花费更高
讲解https的原理或者说过程
关键词:建立ssl连接、协商ssl连接的安全等级、会话密钥
浏览器发起ssl连接请求,服务器返回安全证书和公钥,浏览器验证证书的有效性后,双方进行ssl安全等级的协商,浏览器生成会话密钥并用公钥加密发给服务器,服务器用自己的私钥解出会话密钥,服务器就可以通过会话密钥加密与客户端之间的通信数据了。
http请求的跨域问题
什么是跨域,浏览器不能执行其他网站的脚本,这是由于浏览器的同源策略导致
什么是同源策略,浏览器对javascript实施的安全限制,只要发起http请求端和接收端的协议、域名、端口任何一个不同,就被当成是不同的域。
跨域的原理:通过各种方式避开浏览器的同源策略限制。
跨域的解决办法
最开始是利用jsonp,但存在一些问题,因为只能发起get请求,且能携带的数据较小,限制较多;后来了解和学习到可以使用proxy在前端文件设置代理解决跨域问题。
还未尝试过的跨域方法有:在服务器设置nginx代理,h5的新特性windows.postMessage()等
六、关闭tcp连接
四次挥手 -- 连接释放报文
第一次挥手浏览器数据发送完毕,向服务器发送连接释放报文fin,第二次挥手服务器应答关闭请求ack,浏览器接收到后处于半关闭状态,即发送数据端连接断开,第三次挥手,服务器数据也发送完毕,向浏览器发送关闭连接请求fin,第四次挥手,浏览器向服务器应答关闭请求ack,并进入两个报文最长寿命后关闭状态,服务器一接收到应答报文后立即进入关闭状态。
七、浏览器渲染
浏览器渲染---客户端即浏览器解析html文件内容并渲染出来的过程:构建dom树、构建css树、dom树和css树结合构建render树、布局、绘制
浏览器的重绘和重排区别?
重排/回流:dom改变影响了元素的几何信息
重绘:dom没有改变布局,只改变元素的外观
影响
重绘和重排会破坏用户的体验,并且让UI展示非常迟缓,相比之下重排影响更大。重绘不一定会重排,重排一定会重绘
如何触发?
任何一次改变渲染树render的信息都会导致一次重绘或重排
Dom节点的添加、删除、更新 ;display ;visibility;移动dom节点或者为节点添加动画 ;用户行为伸缩窗口大小
如何避免?
样式集中改变;不要把dom节点元素放入循环中作为变量;为动画元素添加fixed或者absolute的position 这样修改他们的css是不会reflow的;不使用table布局 因为一个小改动都会造成整个table 的重新布局;尽量只修改fixed或者position:absolute的元素 这样对其他元素影响不大;
八、JS引擎解析
Js引擎解析---即调用js引擎执行js代码:
1、创建window对象 也叫全局执行环境,当页面产生时就被创建,所有的全局变量和函数都属于window的属性和方法,dom树也会映射在window 的document对象上,当关闭网页或关闭浏览器时,全局执行环境就被销毁。
2、加载文件 分析语法和词法是否合法,合法则进入预编译。
3、预编译 预编译过程浏览器会寻找全局变量声明,将它加入window属性中,并赋值‘undefined’,寻找全局函数声明,将它加入window方法中,并赋值函数体(匿名函数不参与预编译,因为它是变量)。
4、解释执行 执行到变量就赋值,如果变量没有定义就直接赋值,在es5非严格模式下这个变量会变成window的一个属性,即变成全局变量。执行到函数,就将函数的环境推到一个环境的栈中,执行完成后再弹出,控制权交还给之前的环境。JS作用域就是这样的执行流机制实现的。
几个关键词:预编译、全局函数声明、JS作用域
一个个来展开
1、关于预编译,注意的点:
1、var和函数的作用域提升:预编译时,条件语句对于全局变量和函数都无限制。
即var定义的全局变量和函数未定义先使用,打印‘undefined’。(对于函数fun来说,只能先使用函数名console.log(fun) 打印‘undefined’,调用函数fun() 则打印‘fun is not a function’)
2、但凡在块级作用域中用var定义了全局变量或进行了函数声明,父级作用域中同名的全局变量或函数就会被屏蔽。
即,因为变量提升到该块级作用域的顶部,而导致了对父级作用域变量的封锁。
3、除了var定义的全局变量和进行了函数声明具有作用域提升的buff,可以未定义先使用,其他方式定义的变量不可以,否则未定义先使用就打印如下:
4、全局作用域、if/for/while作用域、函数作用域
全局作用域和if/for/while作用域定义的var和进行的函数声明会被提升到全局属性中,即可以在全局中被访问
函数作用域区别于前两者,var定义的变量和进行的函数声明不会被添加到全局window属性中,即不可以在全局中被访问
三者都可以向父级作用域查找变量;
if/for/while作用域里的var变量和函数声明是可以被父级作用域访问的,即,在预编译时作用域提升了
2、全局函数声明
变量提升不合理的地方在es6中已经解决了,但函数提升还存在
函数声明不是函数定义var fun = function(){} ,而是function fun() {}
3、JS作用域
关键词:什么叫作用域,两种作用域、作用域的作用
定义:简单来说作用域就是变量和函数的可访问范围,由当前环境和上层环境的一系列变量组成
全局作用域:代码在程序的任何地方都能被访问,window 对象的内置属性都拥有全局作用域
函数作用域:在固定的代码片段内才能被访问。
作用:作用域最大的作用就是隔离变量,不同作用域下同名变量不会冲突。
作用域链:一般情况下,变量会到创建该变量的作用域中取值,但如果该作用域中没有查到,就会向上级作用域中查找,直到查到全局作用域,这样查找过程形成的链条就叫做作用域链。