内容:
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:
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