浏览器缓存

缓存的作用
  • 减少了冗余数据的传输,节省了网费。
  • 减少了服务器的负担,提高网站的性能

缓存分为强制缓存和协商缓存

  • 强缓存如果生效不需要再和服务器发生交互,对比缓存不管生不生效都需要与服务端发生交互
  • 两类缓存可以同时存在,强缓存的优先级高于对比缓存
1.对比缓存(协商缓存)
  1. 通过最后修改时间来判断缓存是否可用(Last-Modified):
    在这里插入图片描述
/** 
 * 1.第一次访问服务器的时候,服务器会返回资源和缓存的标识,客户端则会把此资源缓存在本地的缓存数据库中。
 * 2.第二次客户端需要此数据的时候,要取得缓存的标识,然后去问下服务器我的资源是否是最新的。
 * 如果是最新的则直接使用缓存数据,如果不是最新的则服务器返回新的资源和缓存规则,客户端根据新的规则缓存新的数据
 */
const http = require("http");
const url = require("url");
const path = require("path");
const fs = require("fs");
const mime  = require("mime");

http.createServer(function(req,res){
    const { pathname } = url.parse(req.url,true);
    const filepath = path.join(__dirname,pathname);
    fs.stat(filepath,(err,stat)=>{
        if(err){
           return sendErr(req,res)
        }else{
            const ifModifiedSince = req.headers['if-modified-since'];
            const LastModified = stat.ctime.toGMTString();
            if(ifModifiedSince == LastModified){
                res.writeHead(304);
                res.end();
            }else{
                return send(req,res,filepath,stat)
            }
        }
    })
}).listen(8080);

function sendErr(req,res){
    res.end('Not Found');
}
function send(req,res,filepath,stat){
    res.setHeader("Content-Type",mime.getType(filepath));
    //把文件的最后修改时间发给客户端,客户端会把此时间保存起来 ,次再获取此资源的时候会把这个时间再发给服务器
    res.setHeader("Last-Modified",stat.ctime.toGMTString());
    fs.createReadStream(filepath).pipe(res);
}

该方法存在的问题:

  1. 某些服务器拿不到文件的最后修改时间,无法判断
  2. 某些文件修改的非常频繁,在秒以下的时间内进行修改 ,Last-Modified 只能精确到秒
  3. 一些文件修改时间改了,但内容没变,我们不希望客户端认为这个文件修改了
  4. 同一个文件处于多个CDN服务器上的时候,内容虽然一样但最后修改时间不一样

2.Etag (协商缓存)

Etag是实体标签的缩写,根据实体内容生成一段hash字符串,可以标识资源的状态,资源发生改变时Etag也随之发生改变,ETag由服务端产生发给客户端。

  • 第一次服务器返回的时候,会把文件的内容算出来一个标识(通常是md5值),发给客户端,
  • 客户端看到Etag的时候,会把此标识符存在客户端,下次再访问服务器的时候,发给服务器
  • 服务器根据两次的值对比判断是否返回新的内容。
    在这里插入图片描述
const http = require("http");
const url = require("url");
const path = require("path");
const fs = require("fs");
const crypto = require("crypto");
const mime  = require("mime");

http.createServer(function(req,res){
    const { pathname } = url.parse(req.url,true);
    const filepath = path.join(__dirname,pathname);
    fs.stat(filepath,(err,stat)=>{
        if(err){
           return sendErr(req,res)
        }else{
            const ifNoneMatch = req.headers['if-none-match'];
            const out = fs.createReadStream(filepath);
            const md5 = crypto.createHash("md5");
            out.on("data",function(data){
                md5.update(data)
            })
            out.on("end",function(data){
                /**
                * mad5 :
                * 相同的输入 相同的输出。
                * 不同的输入不同的输出。
                * 不能从输出反推输入
                */
               const Etag = md5.digest("hex");
               if(ifNoneMatch == Etag){
                   res.writeHead(304);
                   res.end();
               }else{
                   return send(req,res,filepath,Etag)
               }
            })
        }
    })
}).listen(8080);

function sendErr(req,res){
    res.end('Not Found');
}

function send(req,res,filepath,Etag){
    res.setHeader("Content-Type",mime.getType(filepath));
    //第一次服务器返回的时候,会把文件的内容算出来一个标识,发给客户端,
    //客户端看到Etag的时候,会把此标识符存在客户端,下次再访问服务器的时候,发给服务器
    res.setHeader("Etag",Etag);
    fs.createReadStream(filepath).pipe(res);
}

强缓存

  • 把资源缓存在客户端,如果客户端需要再次使用此资源的时候,先获取到缓存中的数据,看是否过期 如果过期了再请求服务器
    Cache-Control的值
    no-cache : 不使用强缓存
    no-store: 强缓存和协商缓存都不使用
    关键代码 ,在响应头中设置
res.setHeader("Cache-Control","max-age=30");

具体实现

/** 
 * 强缓存
 * 把资源缓存在客户端,如果客户端需要再次使用此资源的时候,先获取到缓存中的数据,看是否过期
 * 如果过期了再请求服务器。
 */
const http = require("http");
const url = require("url");
const path = require("path");
const fs = require("fs");
const mime  = require("mime");

http.createServer(function(req,res){
    const { pathname } = url.parse(req.url,true);
    const filepath = path.join(__dirname,pathname);
    fs.stat(filepath,(err,stat)=>{
        if(err){
           return sendErr(req,res)
        }else{
            return send(req,res,filepath,stat)
        }
    })
}).listen(8080);

function sendErr(req,res){
    res.end('Not Found');
}
function send(req,res,filepath,stat){
    res.setHeader("Content-Type",mime.getType(filepath));
    res.setHeader("Cache-Control","max-age=30");
    fs.createReadStream(filepath).pipe(res);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值