js前端面試常見瀏覽器緩存強緩存及協商緩存實例
前言
最近在背面試題時,時常會看見瀏覽器緩存,雖然沒有用過但是從它的描寫中大致是知道它的作用和重要性。但是還是沒有代碼實操過,也是一知半解的,這口氣咽不下啊,開始找資料,但是大部分都是理論半行代碼沒有,終於東拼西湊頓悟瞭。開始搭環境,幹活。
瀏覽器緩存
瀏覽器緩存是瀏覽器在本地磁盤對用戶最近請求過的文檔進行存儲,當訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁盤加載文檔。 瀏覽器緩存主要分為強緩存(也稱本地緩存)和協商緩存(也稱弱緩存)。
強緩存
當請求資源的時,如果是之前請求過的並使用強緩存,那麼在過期時間內將不會發送本次請求向服務器獲取資源,而是直接從瀏覽器緩存中獲取(不管資源是否改動)。過期瞭將重新從服務器獲取,並再次強緩存。
協商緩存
當請求資源時,如果是之前請求過的並使用協商緩存,還是發送請求到服務器,服務器通過邏輯判斷確認資源沒有修改返回304狀態碼,那麼本次的資源則是從緩存中獲取;如果經過判斷確認資源被修改過,則重新發送資源到客戶端,並且客戶端更新緩存。
判斷資源是否修改有兩種標準,一種是判斷最後修改時間是否變瞭(確實是修改瞭,但資源的內容可以沒有變),另一種是判斷資源的內容是否修改。
使用緩存有下面的優點:
- 減少冗餘的數據傳輸
- 減少服務器負擔
- 加快客戶端加載網頁的速度
搭建環境
- 創建文件夾app,並在下創建app.js 和 fs/a.txt(裡面隨便寫東西)
我們使用node+koa2來搭建我們需要的環境,安裝koa、安裝路由
npm install koa --save npm install koa-router --save
app.js
var Koa = require('koa'); var app = new Koa(); var Router = require('koa-router')(); const fs = require('fs') Router.get("/", async (ctx) => { ctx.body = "ok" }) app .use(Router.routes()) //啟動路由 .use(Router.allowedMethods()); app.listen(3000);
啟動服務器,網頁輸入網址127.0.0.1:3000,環境搭建成功
強緩存
強緩存是利用http頭中的Expires和Cache-Control兩個字段來控制的,Expires是http1.0的規范,Cache-Control是在http1.1中出現的,我們這裡使用Cache-Control示范。
Cache-Control有一些常設置的值
- private:僅瀏覽器可以緩存(默認值);
- public:瀏覽器和代理服務器都可以緩存;
- max-age=xxx:過期時間單位秒;
- no-cache:不進行強緩存;
- no-store:不強緩存,也不協商緩存)
將上面 / 路由的代碼改為
Router.get('/', async (ctx) => { const getResource = () => { return new Promise((res) => { fs.readFile("./fs/a.txt", (err, data) => { if (err) { return; } res(data) }) }) } ctx.set('Cache-Control', 'max-age=10') //設置強緩存,過期時間為10秒 ctx.body = await getResource(); })
將測試搭建環境頁面關閉,重新打開網頁訪問127.0.0.1:3000
前端頁面響應頭多瞭Cache-Control這個字段,且10s內都走本地緩存,不會去請求服務端
在過期時間內再次請求資源,就可以看到這次請求並沒有經過服務器
協商緩存
主要涉及到兩組header字段:Etag和If-None-Match、Last-Modified和if-modified-since。
Etag和If-None-Match
Etag/If-None-Match返回的是一個校驗碼。ETag可以保證每一個資源是唯一的,資源變化都會導致ETag變化。服務器根據瀏覽器上送的If-None-Match值來判斷是否命中緩存。 當服務器返回304 Not Modified的響應時,由於ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化。
Last-Modify和if-modified-since
瀏覽器第一次請求一個資源的時候,服務器返回的header中會加上Last-Modify,Last-Modify是一個時間標識該資源的最後修改時間,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。
當瀏覽器再次請求該資源時,request的請求頭中會包含 if-modified-since,該值為緩存之前返回的Last-Modify。服務器收到if-modified-since後,根據資源的最後修改時間判斷是否命中緩存。
如果命中緩存,則返回304,並且不會返回資源內容,並且不會返回Last-Modify。
樣例我們使用Last-Modify和if-modified-since來實現。對於Etag和If-None-Match的實現,讀取資源內容,轉成hash值,然後跟Last-Modify和if-modified-since的實現差不多瞭,同一個道理。
新添加一個路由器
Router.get('/pp', async (ctx) => { const ifModifiedSince = ctx.request.header['if-modified-since']; const getResource = () => { return new Promise((res) => { fs.stat("./fs/a.txt", (err, stats) => { if (err) { console.log(err); } res(stats) }) }) } let resource = await getResource(); // atime Access Time 訪問時間 // 最後一次訪問文件(讀取或執行)的時間 // ctime Change Time 變化時間 // 最後一次改變文件(屬性或權限)或者目錄(屬性或權限)的時間 // mtime Modify Time 修改時間 // 最後一次修改文件(內容)或者目錄(內容)的時間 if (ifModifiedSince === resource.mtime.toGMTString()) { //把具體的日期轉換為(根據 GMT)字符串 ctx.status = 304; } ctx.set('Last-Modified', resource.mtime.toGMTString()); ctx.body = resource })
關閉頁面,重新打開網頁訪問127.0.0.1:3000/pp
第一次請求,是沒有if-modified-since字段的
第二次請求,沒有修改資源,返回狀態碼304,從緩存獲取資源
修改a.txt文件裡內容時,重新請求服務器
以上就是js前端面試常見瀏覽器緩存強緩存及協商緩存實例的詳細內容,更多關於js前端面試瀏覽器緩存的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 基於HTTP瀏覽器緩存機制全面解析
- node強緩存和協商緩存實戰示例
- 如何利用node實現靜態文件緩存詳解
- web面試常問http緩存解析相關
- SpringMVC中的http Caching的具體使用