## http的緩存
前后端的http交互中,使用緩存能很大程度上的提升效率,而且基本上對性能有要求的前端項目都是必用緩存的
### 強緩存與弱緩存
緩存可以簡單的劃分成兩種類型:`強緩存`(`200 from cache`)與`協商緩存`(`304`)
區別簡述如下:
- 強緩存(`200 from cache`)時,瀏覽器如果判斷本地緩存未過期,就直接使用,無需發起http請求
- 協商緩存(`304`)時,瀏覽器會向服務端發起http請求,然后服務端告訴瀏覽器文件未改變,讓瀏覽器使用本地緩存
對于協商緩存,使用`Ctrl + F5`強制刷新可以使得緩存無效
但是對于強緩存,在未過期時,必須更新資源路徑才能發起新的請求(更改了路徑相當于是另一個資源了,這也是前端工程化中常用到的技巧)
### 緩存頭部簡述
上述提到了強緩存和協商緩存,那它們是怎么區分的呢?
答案是通過不同的http頭部控制
先看下這幾個頭部:
```
If-None-Match/E-tag、If-Modified-Since/Last-Modified、Cache-Control/Max-Age、Pragma/Expires
```
這些就是緩存中常用到的頭部,這里不展開。僅列舉下大致使用。
屬于強緩存控制的:
```
(http1.1)Cache-Control/Max-Age
(http1.0)Pragma/Expires
```
注意:**Max-Age不是一個頭部,它是Cache-Control頭部的值**
屬于協商緩存控制的:
```
(http1.1)If-None-Match/E-tag
(http1.0)If-Modified-Since/Last-Modified
```
可以看到,上述有提到`http1.1`和`http1.0`,這些不同的頭部是屬于不同http時期的
再提一點,其實HTML頁面中也有一個meta標簽可以控制緩存方案-`Pragma`
```
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
```
不過,這種方案還是比較少用到,因為支持情況不佳,譬如緩存代理服務器肯定不支持,所以不推薦
### 頭部的區別
首先明確,http的發展是從http1.0到http1.1
而在http1.1中,出了一些新內容,彌補了http1.0的不足。
**http1.0中的緩存控制:**
- `Pragma`:嚴格來說,它不屬于專門的緩存控制頭部,但是它設置`no-cache`時可以讓本地強緩存失效(屬于編譯控制,來實現特定的指令,主要是因為兼容http1.0,所以以前又被大量應用)
- `Expires`:服務端配置的,屬于強緩存,用來控制在規定的時間之前,瀏覽器不會發出請求,而是直接使用本地緩存,注意,Expires一般對應服務器端時間,如`Expires:Fri, 30 Oct 1998 14:19:41`
- `If-Modified-Since/Last-Modified`:這兩個是成對出現的,屬于協商緩存的內容,其中瀏覽器的頭部是`If-Modified-Since`,而服務端的是`Last-Modified`,它的作用是,在發起請求時,如果`If-Modified-Since`和`Last-Modified`匹配,那么代表服務器資源并未改變,因此服務端不會返回資源實體,而是只返回頭部,通知瀏覽器可以使用本地緩存。`Last-Modified`,顧名思義,指的是文件最后的修改時間,而且只能精確到`1s`以內
**http1.1中的緩存控制:**
- `Cache-Control`:緩存控制頭部,有no-cache、max-age等多種取值
- `Max-Age`:服務端配置的,用來控制強緩存,在規定的時間之內,瀏覽器無需發出請求,直接使用本地緩存,注意,Max-Age是Cache-Control頭部的值,不是獨立的頭部,譬如`Cache-Control: max-age=3600`,而且它值得是絕對時間,由瀏覽器自己計算
- `If-None-Match/E-tag`:這兩個是成對出現的,屬于協商緩存的內容,其中瀏覽器的頭部是`If-None-Match`,而服務端的是`E-tag`,同樣,發出請求后,如果`If-None-Match`和`E-tag`匹配,則代表內容未變,通知瀏覽器使用本地緩存,和Last-Modified不同,E-tag更精確,它是類似于指紋一樣的東西,基于`FileEtag INode Mtime Size`生成,也就是說,只要文件變,指紋就會變,而且沒有1s精確度的限制。
**Max-Age相比Expires?**
`Expires`使用的是服務器端的時間
但是有時候會有這樣一種情況-客戶端時間和服務端不同步
那這樣,可能就會出問題了,造成了瀏覽器本地的緩存無用或者一直無法過期
所以一般http1.1后不推薦使用`Expires`
而`Max-Age`使用的是客戶端本地時間的計算,因此不會有這個問題
因此推薦使用`Max-Age`。
注意,如果同時啟用了`Cache-Control`與`Expires`,`Cache-Control`優先級高。
**E-tag相比Last-Modified?**
`Last-Modified`:
- 表明服務端的文件最后何時改變的
- 它有一個缺陷就是只能精確到1s,
- 然后還有一個問題就是有的服務端的文件會周期性的改變,導致緩存失效
而`E-tag`:
- 是一種指紋機制,代表文件相關指紋
- 只有文件變才會變,也只要文件變就會變,
- 也沒有精確時間的限制,只要文件一改變,立馬E-tag就不一樣了
如果同時帶有`E-tag`和`Last-Modified`,服務端會優先檢查`E-tag`
各大緩存頭部的整體關系如下圖
:-: 
- Web 開發筆記
- 從輸入 URL 到頁面加載完成的過程中都發生了什么事情?
- 從瀏覽器接收url到開啟網絡請求線程
- 開啟網絡線程到發出一個完整的http請求
- 從服務器接收到請求到對應后臺接收到請求
- 后臺和前臺的http交互
- http的緩存
- 解析頁面流程
- HTML解析,構建DOM
- CSS解析,構建CSSOM
- 資源外鏈的下載
- CSS的可視化格式模型
- 包含塊(Containing Block)
- 控制框(Controlling Box)
- BFC(Block Formatting Context)
- IFC(Inline Formatting Context)
- 其它
- JS引擎解析過程
- JS的解釋階段
- JS的預處理階段
- JS的執行階段
- 回收機制
- 參考資料
- JavaScript模塊化編程
- AMD
- requireJS
- CommonJS
- UMD
- ES6模塊
- 參考資料
- 使用 JavaScript 實現一門編程語言
- 如何使用 JavaScript 實現一門編程語言(1) —— 前言
- 如何使用 JavaScript 實現一門編程語言(2) —— 編寫一個解析器
- 如何使用 JavaScript 實現一門編程語言(3) —— Input stream
- 如何使用 JavaScript 實現一門編程語言(4) —— Token stream
- 如何使用 JavaScript 實現一門編程語言(5) —— AST
- 如何使用 JavaScript 實現一門編程語言(6) —— Interpreter
- 完整代碼
- 參考資料
- 前端布局概論
- 參考資料
- Windows 筆記
- 錯誤解決
- win10應用商店無法登錄提示0x80070426解決方法
- 使用技巧
- 設置 Hyper-V 和 VMware 共存
- Powershell
- WSL