內容:
1.緩存基本原理
2.node實現緩存
1.緩存基本原理
第一重要、緩存策略:
- cache-control:用於控制緩存,常見的取值有private、no-cache、max-age、must-revalidate等,默認為private
- expires:失效時間
第二重要、緩存實現過程:
- 第一次Server->Client:"Last-Modified: Sat, 02 Dec 2017 04:03:14 GMT" --> 服務端告訴客戶端資源修改的時間
- 第二次Client->Server:"If-Modified-Since: Sat, 02 Dec 2017 04:03:14 GMT" --> 瀏覽器告訴服務器自己緩存的資源的修改時間
- 第二次Server->Client:200 || 304 --> 服務器根據兩者時間是否相同決定返回200(返回新資源)還是304(叫瀏覽器用自己緩存的資源)
注意:
- cookie不屬於緩存!
- 關於localstorage:https://www.cnblogs.com/st-leslie/p/5617130.html
2.node實現緩存
源碼:
1 const http=require('http'); 2 const fs=require('fs'); 3 const url=require('url'); 4 5 // 連續兩次訪問: http://localhost:8080/1.html 第一次是200 第二次是304 6 http.createServer((req, res)=>{ 7 let {pathname}=url.parse(req.url); 8 9 //獲取文件日期 10 fs.stat(`www${pathname}`, (err, stat)=>{ 11 if(err){ 12 res.writeHeader(404); 13 res.write('Not Found'); 14 res.end(); 15 }else{ 16 // 請求頭中有if-modified-since -> 不是第一次請求,之前瀏覽器中緩存了該頁面 17 if(req.headers['if-modified-since']){ 18 let oDate=new Date(req.headers['if-modified-since']); 19 let time_client=Math.floor(oDate.getTime()/1000); 20 let time_server=Math.floor(stat.mtime.getTime()/1000); 21 22 if(time_server>time_client){ // 服務器的文件時間 > 客戶端手里的版本 23 sendFileToClient(); 24 }else{ 25 res.writeHeader(304); 26 res.write('Not Modified'); 27 res.end(); 28 } 29 } 30 // 請求頭中沒有if-modified-since -> 第一次請求 -> 直接返回要的文件 31 else{ 32 sendFileToClient(); 33 } 34 35 // 直接返回文件 36 function sendFileToClient(){ 37 //發送 38 let rs=fs.createReadStream(`www${pathname}`); 39 40 res.setHeader('Last-Modified', stat.mtime.toGMTString()); 41 42 //輸出 43 rs.pipe(res); 44 45 rs.on('error', function(err){ 46 res.writeHeader(404); 47 res.write('Not Found'); 48 res.end(); 49 }); 50 } 51 } 52 }); 53 }).listen(8080);
原理:
- 服務端第一次向客戶端發送資源時設置文件修改時間:setHeader('Last-Modified', stat.mtime.toGMTString())
- 之后客戶端向瀏覽器請求時服務端檢查請求頭中是否有if-modified-since:
- 如果有if-modified-since就判斷服務器時間是否大於瀏覽器時間(若大於說明服務端文件已經修改就將新修改的文件返回,否則就返回304瀏覽器會直接使用原先緩存的資源)
- 如果沒有if-modified-since就直接返回文件並像最上面那樣設置文件修改時間
另外還可以設置緩存:
1 // 具有緩存控制的服務器 --> 設置Cache-Control(no-cache) 2 const http=require('http'); 3 const fs=require('fs'); 4 const url=require('url'); 5 6 // 連續兩次訪問: http://localhost:8080/1.html 第一次是200 第二次是304 7 http.createServer((req, res)=>{ 8 let {pathname}=url.parse(req.url); 9 10 //獲取文件日期 11 fs.stat(`www${pathname}`, (err, stat)=>{ 12 if(err){ 13 res.writeHeader(404); 14 res.write('Not Found'); 15 res.end(); 16 }else{ 17 // 請求頭中有if-modified-since -> 不是第一次請求,之前瀏覽器中緩存了該頁面 18 if(req.headers['if-modified-since']){ 19 let oDate=new Date(req.headers['if-modified-since']); 20 let time_client=Math.floor(oDate.getTime()/1000); 21 let time_server=Math.floor(stat.mtime.getTime()/1000); 22 23 if(time_server>time_client){ // 服務器的文件時間 > 客戶端手里的版本 24 sendFileToClient(); 25 }else{ 26 res.writeHeader(304); 27 res.write('Not Modified'); 28 res.end(); 29 } 30 } 31 // 請求頭中沒有if-modified-since -> 第一次請求 -> 直接返回要的文件 32 else{ 33 sendFileToClient(); 34 } 35 36 // 直接返回文件 37 function sendFileToClient(){ 38 //發送 39 let rs=fs.createReadStream(`www${pathname}`); 40 41 // 設置緩存 42 res.setHeader('Cache-Control', 'no-cache'); 43 res.setHeader('Last-Modified', stat.mtime.toGMTString()); 44 45 //輸出 46 rs.pipe(res); 47 48 rs.on('error', function(err){ 49 res.writeHeader(404); 50 res.write('Not Found'); 51 res.end(); 52 }); 53 } 54 } 55 }); 56 }).listen(8080); 57