前端知识体系(3)-浏览器篇

9,601

1.从URL输入到页面展现发生了什么

image.png

  1. DNS 解析: 将域名解析成 IP 地址
  2. TCP 连接:TCP 三次握手
  3. 发送 HTTP 请求
  4. 服务器处理请求并返回 HTTP 报文
  5. 浏览器解析渲染页面,构建dom树,样式树,渲染树,layout布局,painting绘制
  6. 断开连接:TCP 四次挥手

详解:

URL 是什么

URL(Uniform Resource Locator),统一资源定位符,俗称网址。用于定位互联网上资源。URL 给资源的位置提供了一种抽象的识别方法,并用这种方法给资源定位,从而对资源进行各种操作,增删改查。

比如 http://www.w3school.com.cn/html/index.asp,遵守以下的语法规则:

scheme://host.domain:port/path/filename

各部分解释如下:

  • scheme - 定义协议的类型。常见的协议有 httphttpsftp(文件传输协议)、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 呢

  1. 浏览器先查询hosts文件是否有与这个域名对应的ip地址,如果则直接向这个ip地址发起http请求。查询不到就进行第二步。(hosts文件位置:C:\Windows\System32\drivers\etc\hosts)

  2. 浏览器向本地DNS服务器发出解析域名的DNS解析报文,本地DNS服务器收到请求后,先查询缓存,判断是否有对应的记录,如果有就返回这条记录,查询不到就进行第三步。

  3. 本地DNS服务器没有在缓存中查询到对应的记录,本地DNS服务器于是就向DNS根服务器发起查询请求。DNS根服务器收到请求通过查询得到顶级域名对应的顶级域服器ip地址,然后向本地DNS服务器发送一条应答报文

  4. 本地DNS服务器收到应答报文后,得到顶级域服务器的地址,然后向该地址发送请求解析域名的DNS请求报文。

  5. 顶级域名服务器在收到请求后先查询缓存是否有对应的记录,如果有就返回对应的记录,如果没有找到就查询域名对应的二级域服务器地址,然后将域名对应的二级域服务器地址返回给本地DNS服务器。

  6. 本地DNS服务器收到应答报文后,得到二级域服务器的地址,然后向该地址发送请求解析域名的DNS请求报文。

  7. 二级域服务器在收到请求后先查询缓存是否有对应的记录,如果有就返回对应的记录,如果没有找到就查询域名对应的三级域服务器地址,然后将域名对应的三级域服务器地址返回给本地DNS服务器。

  8. 本地DNS服务器收到应答报文后,得到三级域服务器的地址,然后向该地址发送请求解析域名的DNS请求报文。

  9. 三级域服务器在收到请求后在DNS区域数据库中查询对应的记录,返回对应的记录

  10. 本地名称服务器在收到三级域服务器后,向用户返回一条DNS应答报文,并将这条记录保存在缓存中

  11. 浏览器就得到了域名对应的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个部分组成,如:

image.png

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)------包含请求的附加信息,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。

请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境请求正文的有用信息。其中比如:

image.png

  • 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-MatchETag一起工作,工作原理是在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、断开连接

image.png 当数据传送完毕,需要断开 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)

image.png

  • 首先,整体的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时增加⼀些头信息:
  • Nginx做反向代理
  • 开发环境跨域使⽤ webpack-dev-server 的 proxy