大家都知道每当页面刷新请求的时候,客户端都向服务端发送请求,然后服务端再把数据(图片,文字等等)发送到客户端,渲染在页面上,但是一个网站中假设有某些资源,例如某些图片,是从网站建立一开始到网站倒闭都不改变的,那难道我们每次打开这个网页都要去请求发送一次图片的资源吗?答案是肯定不是,在浏览器中,如不是很重要的数据都是可以作为缓存存在浏览器中,好比图片,假如之前打开过这个网页也加载过这个图片,那么当我下次再打开这个网页时,我即直接可以从浏览器缓存中拿取图片进行渲染,而不需要从服务端发送数据给我,如此一来即省流量还提高了效率。
接下来我们就详细说明一下如何去判断保存缓存的。
缓存:(是一个服务器和客户端双方协商的过程,可以极大的节省带宽资源)
1.第一次请求的时候 服务器->客户端:Last-Modified
首先当浏览器第一次打开某个网页的时候,服务器会向客户端返回一个last-modified的一个时间,这个时间就是客户端的请求资源的更新的时间
2.第二次客户端->服务器:If-Modified-Since
第二次浏览器再次请求的时候,客户端的请求头中会有一个if-modified-since,这个里面存的就是第一次服务器给的last-modified的时间,然后服务器会将客户端传来的if-modified-since与自己本身的这个资源的更新时间进行对比,如和if-modified-since的时间是一样的,那说明服务端中的资源没有改变,客户端手里的资源就是最新的,即不需要服务端进行数据传输,直接从浏览器缓存中拿取即可
3.第二次服务器->客户端:304 || 200
如缓存中的资源为最新,则服务器返回304.即不需要数据传输
下面是写的一个缓存小例子
const http = require('http');
const fs = require('fs');
const url = require('url');
const server = http.createServer((req, res) => {
let {
pathname
} = url.parse(req.url);
// 获取文件的日期
fs.stat('www' + pathname, (err, stat) => {
if (err) { // 这里的判断只是一时的,有可能文件读取一半就终止了
res.writeHeader(404);
res.write('not found');
res.end();
} else {
if (req.headers['if-modified-since']) {
let newDate = new Date(req.headers['if-modified-since']);
let time_client = Math.floor(newDate.getTime()/1000);
let time_server = Math.floor(stat.mtime.getTime()/1000);
if (time_client < time_server) { // 服务器文件的时候大于客户端文件时间的版本
sendMsg();
} else {
res.writeHeader(304);
res.write('not modified');
res.end();
}
} else {
console.log('1:'+req.headers['if-modified-since']);
sendMsg();
}
}
function sendMsg() {
// 发送
let rs = fs.createReadStream('www' + pathname);
res.setHeader('Last-Modified', stat.mtime.toGMTString());
// 输出
rs.pipe(res);
rs.on("error", err => { // 这里的判断是持续的
res.writeHeader(404);
res.write('not found');
res.end();
})
}
})
}).listen(8080)
当然如果是传输比较隐私的数据例如密码,这个我们可以控制不要缓存,通过Cache-Control设置no-cache即可