Skip to content

Commit

Permalink
update 前端本地缓存概况之浏览器缓存策略
Browse files Browse the repository at this point in the history
  • Loading branch information
yangpeng14 committed Jul 10, 2020
1 parent efbcea1 commit 9cdee6b
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 23 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/15942217205747.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/15942217704692.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions ops/前端本地缓存概况之浏览器缓存策略.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

内存缓存,主要包含页面中已经获取到的资源,比如页面的脚本文件、样式文件、图片等,内存的读取速度要比磁盘快。该缓存属于 `会话级别`,一但会话结束,则缓存资源被释放。此外内存容量所限,该缓存更多存储小体积的请求资源。

![](https://shenggao.oss-cn-beijing.aliyuncs.com/blog/2020/07/09/15942217205747.jpg)
![](/img/15942217205747.jpg)

该缓存主要关注当前会话中第一次请求返回中,`response-headers` 中的 `cache-control``Expires` 两个字段情况,一经识别计算通过,则资源将被存储于内存中。(一般cdn都会配置该策略)

Expand All @@ -50,7 +50,7 @@

其具体缓存机制与 `memory cache` 一致,只是可以存储的数据量比较大,但是相对来说读取略慢,比较内存缓存来说,硬盘缓存的优点主要体现在时效性上和容量上。硬盘缓存中存入的数据也是根据 `http header` 中的字段判定的。哪些资源可以进行存储,哪些不进行存储。

![](https://shenggao.oss-cn-beijing.aliyuncs.com/blog/2020/07/09/15942217704692.jpg)
![](/img/15942217704692.jpg)

`disk cache` 不同于 `memory cache`,disk cache的资源是从磁盘当中取出的,也是在已经在之前的某个时间加载过该资源,不会请求服务器,但是此资源不会随着该页面的关闭而释放掉,因为是存在硬盘当中的,下次打开仍会 `from disk cache`

Expand All @@ -63,48 +63,50 @@

### 2、协商缓存(对比缓存)

协商缓存就是**强制缓存失效**后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,需要强调的是,这个过程是**需要发出请求的**
协商缓存就是 `强制缓存失效` 后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,需要强调的是,这个过程是 `需要发出请求的`

**备注**
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
`备注`

#### 304
强制缓存优先于协商缓存进行,若强制缓存 (Expires 和 Cache-Control) 生效则直接使用缓存,若不生效则进行协商缓存( Last-Modified / If-Modified-Since 和 Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。

![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2019/png/84653/1558062783657-92e4fc45-38a8-4c6e-84c0-1a7a890ef07c.png#align=left&display=inline&height=407&name=image.png&originHeight=407&originWidth=800&size=106021&status=done&width=800)
#### 304

Http 304 状态请求

![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2019/png/84653/1558439341166-a01890a7-d933-4292-b1b1-2536d27ef52c.png#align=left&display=inline&height=900&name=image.png&originHeight=900&originWidth=1221&size=85640&status=done&width=1221)
![](/img/1558062783657-92e4fc45-38a8-4c6e-84c0-1a7a890ef07c.png)

文件有更新,协商缓存失效,返回200及相关数据资源

![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2019/png/84653/1558439296918-b969ce9c-32a1-4500-bb77-ae0496146822.png#align=left&display=inline&height=901&name=image.png&originHeight=901&originWidth=1225&size=97526&status=done&width=1225)
![](/img/1558439341166-a01890a7-d933-4292-b1b1-2536d27ef52c.png)

文件未更新,协商缓存生效,返回304及空响应及,浏览器直接读取缓存资源

如图所示,http请求携带的缓存标识可以有两个,分别是 Last-modified和Etag,接下来我们慢慢说一说这两个。
![image.png](/img/1558439296918-b969ce9c-32a1-4500-bb77-ae0496146822.png)

**Last-modified和if-Modified-since**
如图所示,http请求携带的缓存标识可以有两个,分别是 `Last-modified``Etag`,接下来我们慢慢说一说这两个。

Last-modified——最后的修改时间,根据比对修改时间可以确定在这一段时间里资源是否进行了修改。
`Last-modified``if-Modified-since`

最小颗粒为S,这颗粒度也就暴露了这个属性的弊端,如果在一秒以内修改多次,则数据不会更新
`Last-modified`:最后的修改时间,根据比对修改时间可以确定在这一段时间里资源是否进行了修改

浏览器第一次请求的时候,响应资源的header中添加 last-modified,数值为资源在服务器的最后修改时间。浏览器下一次请求的时候,检测到先前返回header中 有“last-modified”属性,则请求上行时header中会添加“if-modified-since”属性,值为与“last-modified”一致
最小颗粒为`S`,这颗粒度也就暴露了这个属性的弊端,如果在一秒以内修改多次,则数据不会更新

服务器再次收到这个资源请求,会根据“If-Modified-Since”中的值与服务器中这个资源的最后修改时间对比,如果两个值相等,返回304和空的响应体,直接约定从浏览器缓存中读取;如果“If-Modified-Since”的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200
浏览器第一次请求的时候,响应资源的 `header` 中添加 `last-modified`,数值为资源在服务器的最后修改时间。浏览器下一次请求的时候,检测到先前返回 `header` 中有`last-modified`属性,则请求上行时 `header` 中会添加 `if-modified-since` 属性,值与 `last-modified` 一致

服务器再次收到这个资源请求,会根据 `If-Modified-Since` 中的值与服务器中这个资源的最后修改时间对比,如果两个值相等,返回状态码`304``空的响应体`,直接约定从浏览器缓存中读取;如果 `If-Modified-Since` 的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回`新的资源文件`和状态码`200`

当然这个“last-modified”是http1.0年代的产物,存在着重大弊端,因为 Last-Modified 只能以秒计时,如果在同一个秒时间内修改了文件,那么此时二次请求服务端,服务端会认为资源未变更,进而返回304,造成资源错误。

**Etag和if-none-macth**
当然这个 `last-modified``http1.0`年代的产物,存在着重大弊端,因为 `Last-Modified` 只能`以秒计时`,如果在同一个秒时间内修改了文件,那么此时二次请求服务端,服务端会认为资源未变更,进而返回304,造成资源错误。

前面说到了“Last-modified和if-Modified-since”组合的弊端,于是在后续的http1.1版本,引入了“Etag和if-none-macth”组合。
`Etag``if-none-macth`

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识,一般是一个hash值,只要资源有变化,Etag就会重新生成
前面说到了 `Last-modified``if-Modified-since` 组合的弊端,于是在后续的http1.1 版本,引入了 `Etag``if-none-macth` 组合

浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到请求上行的header中“If-None-Match”属性里,服务器只需要比较客户端传来的header-“If-None-Match”值跟自己服务器上该资源的Etag是否一致,就能直接判断资源相对客户端缓存而言是否有修改。如果服务器发现Etag匹配不上,那么直接返回状态码200及新资源(当然也包括了新的Etag);如果匹配是一致的,则直接返回304和空的响应体,直接约定从浏览器缓存中读取。这里就避免了“last-modified”的秒级误差问题。至此,我们已经介绍了3种缓存:memory cache、disk cache、304,那么我们下面用一张流线图描述下请求及缓存过程:
`Etag` 是服务器响应请求时,返回当前资源文件的一个唯一标识,一般是一个`hash值`,只要资源有变化,Etag就会重新生成。

![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2019/png/84653/1558489929900-b9afc3e5-c183-4622-93ca-a2c2a49b7a17.png#align=left&display=inline&height=808&name=image.png&originHeight=808&originWidth=1258&size=97873&status=done&width=1258)
浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的`Etag值`放到请求上行的`header``If-None-Match` 属性里,服务器只需要比较客户端传来的 `header` `If-None-Match` 值跟自己服务器上该资源的Etag是否一致,就能直接判断资源相对客户端缓存而言是否有修改。如果服务器发现Etag匹配不上,那么直接返回状态码200及新资源(当然也包括了新的Etag);如果匹配是一致的,则直接返回304和空的响应体,直接约定从浏览器缓存中读取。这里就避免了 `last-modified``秒级误差问题`。至此,我们已经介绍了3种缓存:`memory cache``disk cache``304`,那么我们下面用一张流线图描述下请求及缓存过程:

![image.png](/img/1558489929900-b9afc3e5-c183-4622-93ca-a2c2a49b7a17.png)

### 测试代码

Expand Down Expand Up @@ -192,5 +194,4 @@ server.on("request",function(req,res){
});
server.listen(PORT);
console.log('Server running at http://127.0.0.1:' + PORT + '/');
```

```

0 comments on commit 9cdee6b

Please sign in to comment.