1.从URL输入到页面展现发生了什么
- DNS 解析: 将域名解析成 IP 地址
- TCP 连接:TCP 三次握手
- 发送 HTTP 请求
- 服务器处理请求并返回 HTTP 报文
- 浏览器解析渲染页面,构建dom树,样式树,渲染树,layout布局,painting绘制
- 断开连接:TCP 四次挥手
详解:
URL 是什么
URL(Uniform Resource Locator),统一资源定位符
,俗称网址。用于定位互联网上资源。URL 给资源的位置提供了一种抽象的识别方法,并用这种方法给资源定位,从而对资源进行各种操作,增删改查。
比如 http://www.w3school.com.cn/html/index.asp
,遵守以下的语法规则:
scheme://host.domain:port/path/filename
各部分解释如下:
- scheme - 定义协议的类型。常见的协议有
http
、https
、ftp
(文件传输协议)、file
(本地文件的协议),其中最常见的类型是 http,而 https 则是进行加密的网络传输。 - host - 定义域主机(http 的默认主机是 www),当然也有
https://zhidao.baidu.com
或者https://map.baidu.com
里面的其它主机名 - domain - 定义因特网域名,比如
w3school.com.cn,baidu.com
- port - 定义主机上的端口号(http 的默认端口号是
80
,https默认443
) - path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
- filename - 定义文档/资源的名称
2、域名解析(DNS)
在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过 IP 地址。大家这里或许会有个疑问----计算机既可以被赋予 IP 地址,也可以被赋予主机名和域名。比如 www.hackr.jp
。那怎么不一开始就赋予个 IP 地址?这样就可以省去解析麻烦。我们先来了解下什么是 IP 地址
2-1. IP 地址
IP 地址是指 互联网协议地址
。它为互联网上的每一个网络
和每一台主机
分配一个逻辑地址
,以此来屏蔽物理地址
的差异。IP 地址是一个 32 位
的二进制数
,比如 127.0.0.1
为本机 IP。 域名就相当于语义化
的IP 地址,便于记忆和沟通。与 IP 地址的一组纯数字相比,用字母配合数字的表示形式来指定计算机名更符合人类的记忆习惯。但要让计算机去理解名称,相对而言就变得困难了。因为计算机更擅长处理一长串数字。为了解决上述的问题,DNS 服务应运而生。
2-2. 什么是域名解析
DNS 协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器
,我们的域名解析简单来说就是在 DNS 上记录一条信息记录
。 例如 baidu.com 220.114.23.56(服务器外网IP地址)80(服务器端口号)
2-3. 浏览器如何通过域名去查询 URL 对应的 IP 呢
-
浏览器先查询
hosts
文件是否有与这个域名对应的ip地址
,如果有则直接向这个ip地址发起http请求。查询不到就进行第二步。(hosts文件位置:C:\Windows\System32\drivers\etc\hosts
) -
浏览器向
本地DNS服务器
发出解析域名的DNS解析报文,本地DNS服务器收到请求后,先查询缓存
,判断是否有对应的记录,如果有就返回这条记录
,查询不到就进行第三步。 -
本地DNS服务器没有在缓存中查询到对应的记录,本地DNS服务器于是就向
DNS根服务器
发起查询请求。DNS根服务器收到请求通过查询
得到顶级域名对应的顶级域服器
的ip地址
,然后向本地DNS服务器发送一条应答报文
。 -
本地DNS服务器收到应答报文后,
得到
顶级域服务器的地址,然后向该地址发送请求解析域名的DNS请求报文。 -
顶级域名服务器在收到请求后先查询缓存是否有对应的记录,如果有就返回对应的记录,如果没有找到就查询域名对应的
二级域服务器
地址,然后将域名对应的二级域服务器地址返回给本地DNS服务器。 -
本地DNS服务器收到应答报文后,得到二级域服务器的地址,然后向该地址发送请求解析域名的DNS请求报文。
-
二级域服务器在收到请求后先查询缓存是否有对应的记录,如果有就返回对应的记录,如果没有找到就查询域名对应的三级域服务器地址,然后将域名对应的三级域服务器地址返回给本地DNS服务器。
-
本地DNS服务器收到应答报文后,得到三级域服务器的地址,然后向该地址发送请求解析域名的DNS请求报文。
-
三级域服务器在收到请求后在DNS区域数据库中查询对应的记录,返回对应的记录
-
本地名称服务器在收到三级域服务器后,向用户返回一条DNS应答报文,并将这条记录保存在缓存中
-
浏览器就得到了域名对应的ip地址,然后就可以发起http请求了
各个域名服务器的解释
- 根服务器主要用来管理互联网的主目录,顶级域如:
https://www.baidu.com
中的.com
- 二级域,如:
https://www.baidu.com
中的baidu.com
- 三级域,如:
https://a.www.baidu.com
中的a.baidu.com
2-4. 小结
浏览器通过向 DNS 服务器发送域名,DNS 服务器查询到与域名相对应的 IP 地址,然后返回给浏览器,浏览器再将 IP 地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。
3、TCP 三次握手
接下来介绍向服务器发送 HTTP 请求阶段,HTTP 请求分为三个部分:TCP 三次握手
、http 请求响应信息
、关闭 TCP 连接
。
在客户端发送数据之前
,会发起 TCP 三次握手用以同步
客户端和服务端的序列号
和确认号
,并交换 TCP 窗口大小信息
。
3-1.TCP 三次握手的过程如下:
- 客户端发送一个带
SYN=1,Seq=X
的数据包到服务器端口(第一次握手,由浏览器发起,告诉服务器我要发送请求了) - 服务器发回一个带
SYN=1, ACK=X+1, Seq=Y
的响应包以示传达确认信息(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧) - 客户端再回传一个带
ACK=Y+1, Seq=Z
的数据包,代表“握手结束”(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)
各个字段的说明:
- SYN表示建立连接
- Seq是序列号,这是为了连接以后传送数据用的
- ACK表示响应,是对收到的数据包的确认,值期望对方继续发送的那个数据包的序列号,因为已经接收了X,期望接收下一个X+1
3-2.为什么要三次握手
这是为了防止无效
的连接请求报文到达服务器
。
因为有可能A先发了一个连接请求报文,但是由于网络的 问题,迟迟没有到达B主机,这时候,A主机就超时重传了该报文,然后B主机响应了该请求报文,但是不妙了,第一个报文居然又到了B主机,那么B主机就会把它作为新的连接请求,如果只有两次握手,那么B主机对于该连接请求也会建立连接,但是如果是三次握手,B主机发出确认报文后,A主机不予理睬,这样就不会建立TCP连接了。
4、发送 HTTP 请求
TCP 三次握手结束后,开始发送 HTTP 请求报文。 请求报文由请求行
(request line)、请求头
(header)、请求体
3个部分组成,如:
4-1. 请求行-----包含请求方法、URL、协议版本
请求方法包含 8 种: GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。 URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数>
组成 协议版本即 http 版本号
POST /chapter17/user.html HTTP/1.1
以上代码中“POST”代表请求方法,“/chapter17/user.html”表示 URL,“HTTP/1.1”代表协议和协议的版本。现在比较流行的是 Http1.1 版本
4-2.请求头(Request Headers)------包含请求的附加信息,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。
请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境
和请求正文
的有用信息。其中比如:
-
Accept
- 作用:浏览器端可以接受的媒体类型
- 例如:
Accept: text/html
代表浏览器可以接受服务器回发的类型为 text/html 也就是我们常说的html文档,如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)。 - 通配符: 代表任意类型, 例如 Accept: * / * 代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)。
-
Accept-Encoding:
- 作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码)
- 例如: Accept-Encoding: gzip, deflate, br
-
Accept-Language
- 作用: 浏览器申明自己接收的语言。
- 语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等
- 例如: Accept-Language: zh-CN,zh;q=0.9
-
Connection
- 作用:
Connection: keep-alive
当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立
的连接
。 - 例如:
Connection: close
代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。
- 作用:
-
Host(发送请求时,该报头域是必需的)
- 作用: 访问的服务器主机名,比如百度的
www.baidu.com
。这个值在爬虫时可以从 访问的 URI 中获 得。 例如: 我们在浏览器中输入:www.baidu.com
,则为:Host: www.baidu.com
- 作用: 访问的服务器主机名,比如百度的
-
Referer
- 浏览器
上次访问
的网页url
,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
- 浏览器
-
User-Agent
- 作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本。
- 例如:User-Agent: Mozilla/5.0
-
Cookie
- Cookie是用来存储一些用户信息以便让服务器辨别用户身份的(大多数需要登录的网站上面会比较常见),比如cookie会存储一些用户的用户名和密码,当用户登录后就会在客户端产生一个cookie来存储相关信息,这样浏览器通过读取cookie的信息去服务器上验证并通过后会判定你是合法用户,从而允许查看相应网页。当然cookie里面的数据不仅仅是上述范围,还有很多信息可以存储是cookie里面,比如sessionid等。
-
If-Modified-Since
- 作用: 把浏览器端缓存页面的
最后修改时间
发送到服务器去,服务器会把这个时间与服务器
上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中 - 例如:
Mon, 17 Aug 2015 12:03:33 GMT
- 作用: 把浏览器端缓存页面的
-
If-None-Match
- 作用:
If-None-Match
和ETag
一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag. 使用这样的机制将提高网站的性能 - 例如:
If-None-Match: W/“3119-1437038474000”
。
- 作用:
-
Authorization `- 当客户端接收到来自WEB服务器的 WWW-Authenticate 响应时,该头部来回应自己的身份验证信息给WEB服务器。主要是授权验证,确定符合服务器的要求
-
Proxy-Connection
- 当使用代理服务器的时候,这个就指明了代理服务器是否使用长链接。但是,数据在从client 到代理服务器,和从代理服务器到被请求的服务器之间如果存在信息差异的话,会造成信息请 求不到,但是在大多数情况下,都还是能够成立的。
4-3.请求体,-------可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。
name=tom&password=1234&realName=tomson
上面代码,承载着 name、password、realName 三个请求参数。
5、服务器处理请求并返回 HTTP 报文
5-1. 服务器
服务器是网络环境中的高性能计算机
,它侦听网络上的其他计算机(客户机)提交的服务请求,并提供相应的服务,比如网页服务、文件下载服务、邮件服务、视频服务。而客户端主要的功能是浏览网页、看视频、听音乐等等,两者截然不同
。 每台服务器上都会安装处理请求的应用——web server
。常见的 web server 产品有 apache、nginx、IIS 或 Lighttpd
等。
web server 担任管控
的角色,对于不同用户发送的请求,会结合配置文件,把不同请求委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端 JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应。
5-2.MVC 后台处理阶段
后台开发现在有很多框架,但大部分都还是按照 MVC 设计模式进行搭建的。 MVC 是一个设计模式,将应用程序分成三个核心部件:模型(model)-- 视图(view)--控制器(controller),它们各自处理自己的任务,实现输入、处理和输出
的分离。
5-2-1、视图(view)
它是提供给用户的操作界面
,是程序的外壳
。
5-2-2、模型(model)
模型主要负责数据
交互。在 MVC 的三个部件中,模型拥有最多的处理任务。一个模型能为多个视图提供数据。
5-2-3、控制器(controller)
它负责根据用户从"视图层"输入的指令,选取"模型层"中的数据,然后对其进行相应的操作,产生最终结果。控制器属于管理者
角色,从视图接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示模型处理返回的数据。
5-3.http 响应报文
响应报文由响应行(request line)、响应头部(header)、响应主体三个部分组成。如下图所示:
(1) 响应行包含:协议版本,状态码,状态码描述
状态码规则如下:
- 1xx:指示信息--表示请求已接收,继续处理。
- 2xx:成功--表示请求已被成功接收、理解、接受。
- 3xx:重定向--要完成请求必须进行更进一步的操作。
- 4xx:客户端错误--请求有语法错误或请求无法实现。
- 5xx:服务器端错误--服务器未能实现合法的请求。
(2) 响应头部包含响应报文的附加信息,由 名/值 对组成
(3) 响应主体包含回车符、换行符和响应返回数据,并不是所有响应报文都有响应数据
6、浏览器解析渲染页面**
浏览器拿到响应文本 HTML 后,接下来介绍下浏览器渲染机制
浏览器解析渲染页面分为一下五个步骤:
- 根据 HTML 解析出 DOM 树
- 根据 CSS 解析生成 CSS 规则树
- 结合 DOM 树和 CSS 规则树,生成渲染树
- 根据渲染树计算每一个节点的信息
- 根据计算好的信息绘制页面
6-1.根据 HTML 解析 DOM 树
根据 HTML 的内容,将标签
按照结构
解析成为 DOM 树
,DOM 树解析的过程是一个深度优先遍历
。即先构建当前节点的所有子节点,再构建下一个兄弟节点。 在读取 HTML 文档,构建 DOM 树的过程中,若遇到 script 标签,则 DOM 树的构建会暂停
(js单线程的原因),直至脚本执行完毕。
6-2.根据 CSS 解析生成 CSS 规则树
解析 CSS 规则树时 js 执行将暂停
,直至 CSS 规则树就绪。 浏览器在 CSS 规则树生成之前不会进行渲染。
6-3.结合 DOM 树和 CSS 规则树,生成渲染树
DOM 树和 CSS 规则树全部准备好了以后,浏览器才会开始构建渲染树。 精简 CSS 并可以加快 CSS 规则树的构建,从而加快页面相应速度。
6-4.根据渲染树计算每一个节点的信息(布局)
重绘:
某个元素的背景颜色,文字颜色等,不影响
元素周围或内部布局
的属性,将只会引起浏览器的重绘。
回流:
某个元素的尺寸
发生了变化,则需重新计算渲染树,重新渲染
回流什么时候发生?
- 添加或者删除可见的DOM元素;
- 元素位置改变;
- 元素尺寸改变——边距、填充、边框、宽度和高度
- 内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
- 页面渲染初始化;
- 浏览器窗口尺寸改变——resize事件发生时;
6-5.根据计算好的信息绘制页面
绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。
7、断开连接
当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。
- 发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧)
- 被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。(第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)
- 被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧)
- 发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。(第四次挥手:由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)
8.浏览器下事件循环(Event Loop)
- 首先,
整体的script
(作为第一个宏任务
)开始执行的时候,会把所有代码分为同步任务、异步任务
两部分 同步
任务会直接进入主线程
依次执行异步
任务会再分为宏
任务和微
任务- 宏任务进入到Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue(事件队列)中
- 微任务也会进入到另一个Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中
- 当主线程内的任务执行完毕,
主线程为空
时,会检查微任务
的Event Queue,如果有任务,就全部执行,如果没有就执行下一个宏任务 - 上述过程会不断重复,这就是Event Loop,比较完整的事件循环
案例:
function test() {
console.log(1)
setTimeout(function () { // timer1
console.log(2)
}, 1000)
}
test();
setTimeout(function () { // timer2
console.log(3)
})
new Promise(function (resolve) {
console.log(4)
setTimeout(function () { // timer3
console.log(5)
}, 100)
resolve()
}).then(function () {
setTimeout(function () { // timer4
console.log(6)
}, 0)
console.log(7)
})
console.log(8)
打印:1,4,8,7,3,6,5,2
解析:
- JS是顺序从上而下执行
- 执行到test(),test方法为同步,直接执行,console.log(1)打印1
- test方法中setTimeout为异步宏任务,回调我们把它记做timer1放入宏任务队列
- 接着执行,test方法下面有一个setTimeout为异步宏任务,回调我们把它记做timer2放入宏任务队列
- 接着执行promise,new Promise是同步任务,直接执行,打印4
- new Promise里面的setTimeout是异步宏任务,回调我们记做timer3放到宏任务队列
- Promise.then是微任务,放到微任务队列
- console.log(8)是同步任务,直接执行,打印8
- 主线程任务执行完毕,检查微任务队列中有Promise.then
- 开始执行微任务,发现有setTimeout是异步宏任务,记做timer4放到宏任务队列
- 微任务队列中的console.log(7)是同步任务,直接执行,打印7
- 微任务执行完毕,第一次循环结束
- 检查宏任务队列,里面有timer1、timer2、timer3、timer4,四个定时器宏任务,按照定时器延迟时间得到可以执行的顺序,即Event Queue:timer2、timer4、timer3、timer1,依次拿出放入执行栈末尾执行 (插播一条:浏览器 event loop 的 Macrotask queue,就是宏任务队列在每次循环中只会读取一个任务)
- 执行timer2,console.log(3)为同步任务,直接执行,打印3
- 检查没有微任务,第二次Event Loop结束
- 执行timer4,console.log(6)为同步任务,直接执行,打印6
- 检查没有微任务,第三次Event Loop结束
- 执行timer3,console.log(5)同步任务,直接执行,打印5
- 检查没有微任务,第四次Event Loop结束
- 执行timer1,console.log(2)同步任务,直接执行,打印2
- 检查没有微任务,也没有宏任务,第五次Event Loop结束
9.重绘与回流
当元素的样式发生变化时,浏览器需要触发更新,重新绘制元素。这个过程中,有两种类型的操作,即重绘与回流。
重绘(repaint):
当元素样式的改变不影响布局
时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此 损耗较少
回流(reflow):
当元素的尺寸、结构
或触发某些属性时,浏览器会重新渲染
页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局
,因此是较重的操作。
会触发回流的操作:
- 页面初次渲染
- 浏览器窗口大小改变
- 元素尺寸、位置、内容发生改变
- 元素字体大小变化
- 添加或者删除可见的 dom 元素
- 激活 CSS 伪类(例如::hover)
- 查询某些属性或调用某些方法
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- getComputedStyle()
- getBoundingClientRect()
- scrollTo()
回流必定触发重绘,重绘不一定触发回流。重绘的开销较小,回流的代价较高。
如何减少回流:
css
- 避免使用table布局
- 将动画效果应用到position属性为absolute或fixed的元素上
javascript
- 避免频繁操作样式,可汇总后统一 一次修改
- 尽量使用class进行样式修改
- 减少dom的增删次数,可使用 字符串 或者 documentFragment 一次性插入
- 极限优化时,修改样式可将其display: none后修改
- 避免多次触发上面提到的那些会触发回流的方法,可以的话尽量用 变量存住
10.存储
我们经常需要对业务中的一些数据进行存储,通常可以分为 短暂性存储
和 持久性储存
。
- 短暂性的时候,我们只需要将数据存在内存中,只在运行时可用
- 持久性存储,可以分为
浏览器端
与服务器端
浏览器:
- cookie: 通常用于存储用户身份,登录状态等 http 中自动携带, 体积上限为 4K, 可自行设置过期时间
- localStorage / sessionStorage: 长久储存/窗口关闭删除, 体积限制为 4~5M
- indexDB
服务器:
- 分布式缓存 redis
- 数据库
11. http/https 协议
11-1. [1.] 协议缺陷:
- 无法复用链接,完成即断开,重新慢启动和 TCP 3次握手
- head of line blocking: 线头阻塞,导致请求之间互相影响
11-2. [1.1] 改进:
- 长连接(默认 keep-alive),复用
- host 字段指定对应的虚拟站点
新增功能:
- 断点续传
- 身份认证
- 状态管理
- cache 缓存
- Cache-Control
- Expires
- Last-Modified
- Etag
11-3. [2.0]:
- 多路复用
- 二进制分帧层: 应用层和传输层之间
- 首部压缩
- 服务端推送
11-4. https: 较为安全的网络传输协议
-证书(公钥)
- SSL 加密
- 端口 443
11-5.缓存策略: 可分为 强缓存 和 协商缓存
11-5-1 强缓存
- Cache-Control:浏览器判断缓存是否过期,
未过期
时,直接使用强缓存
,Cache-Control的 max-age 优先级高于
Expires - Expires: 浏览器判断缓存是否过期
当缓存已经过期时,使用协商缓存
11-5-2 协商缓存
1. 唯一标识方案:
- Etag(
response
携带) - If-None-Match(
request
携带,上一次返回的Etag
) -- 服务器判断资源是否被修改
ETag/If-None-Match ETag可以保证每⼀个资源是唯⼀的,资源变化都会导致ETag变化。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。
缺点:
因为这个时间是⼀个绝对时间,所以当客户端本地时间被修改后,服务器与客户端时间偏差变⼤会 导致缓存混乱。
2. 最后一次修改时间方案:
Last-Modified(
response
) & If-Modified-Since (request
,上一次返回的Last-Modified)
- 如果一致,则直接返回 304 通知浏览器使用缓存
- 如不一致,则服务端返回新的资源
Last-Modify/If-Modify-Since 浏览器第⼀次请求⼀个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是⼀个时间标识该资源的最后修改时间,当浏览器再次请求该资源时,发送的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If.Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
Last-Modified 缺点:
- 周期性修改,但内容未变时,会导致缓存失效
- 最小粒度只到 s, s 以内的改动无法检测到
Etag 的优先级高于 Last-Modified
12. 跨域
什么是同源策略:
同源策略是指协议、端⼝、域名相同,也就是在同⼀个域中。
⾮同源受到的限制:
cookie⽆法读取、dom⽆法获取、ajax请求⽆法发送。
什么是跨域:
两个不同域(协议、端⼝、域名不同)之间进⾏请求。
解决跨域的⽅法:
- JSONP,通过动态创建⼀个script标签,script标签的src属性是没有跨域的限制的。
- cors,服务端在response时增加⼀些头信息:
- Access-Control-Allow-Origin: http://ip:port
- Nginx做反向代理
- 开发环境跨域使⽤ webpack-dev-server 的 proxy