• Node.js实现浏览器缓存


            图 1 使用缓存的流程示意图

    下面从三个规则分别来讲:

    1. 添加Expires或Cache-Control到报文头中;
    2. 配置Etags;
    3. 让Ajax缓存。
    • 条件请求

    请求头部设置了If-Modified-Since,浏览器向服务器请求资源,服务端返回304状态码,浏览器则会使用本地文件。

    var handle = function (req, res) {
        fs.stat(filename, function (err, stat) {
            var lastModified = stat.mtime.toUTCString();
            if (lastModified === req.headers['if-modified-since']) {
                res.writeHead(304, "Not Modified");
                res.end();
            } else {
                fs.readFile(filename, function(err, file) {
                    var lastModified = stat.mtime.toUTCString();
                    res.setHeader("Last-Modified", lastModified);
                    res.writeHead(200, "Ok");
                    res.end(file);
                });
            }
        });
    };

    这里采用时间戳的方式来实现,时间戳的方式有一些缺陷:

    文件的时间戳改动了但内容不一定改动。

    时间戳只能精确到秒级别,更新频繁的内容将无法生效。

    Etags(Entity Tag)可以解决这个问题,由服务端生成,生成规则随意。一般是根据文件内容生成散列值,那么条件请求将不会受到时间戳改动造成带宽的浪费。与If-Modified-Since/Last-Modified不同的是,Etags的请求相应是:If-None-Match/ETag

    var getHash = function (str) {
        var shasum = crypto.createHash('sha1');
        return shasum.update(str).digest('base64');
    };
    var handle = function (req, res) {
        fs.readFile(filename, function(err, file) {
            var hash = getHash(file);
            var noneMatch = req.headers['if-none-match'];
            if (hash === noneMatch) {
                res.writeHead(304, "Not Modified");
                res.end();
            } else {
                res.setHeader("ETag", hash);
                res.writeHead(200, "Ok");
                res.end(file);
            }
        });
    };

    尽管条件请求可以在文件内容没有改变的情况下节省带宽,但是还是需要请求服务器,那么可以不请求服务器直接取本地文件吗?

    • 非条件请求(在服务端响应内容时,让浏览器明确地将内容缓存起来)

    Expires是一个GMT格式的时间字符串(GMT时间与北京时间相互可以转化),在服务器端设置Expires可以告知浏览器要缓存的内容,只要本地还存在这个文件,在过期时间之前,都不会再发起请求。

    var handle = function (req, res) {
        fs.readFile(filename, function(err, file) {
            var expires = new Date();
            expires.setTime(expires.getTime() + 10 * 365 * 24 * 60 * 60 * 1000);
            res.setHeader("Expires", expires.toUTCString());
            res.writeHead(200, "Ok");
            res.end(file);
        });
    };

    *缺陷:如果用户本地时间和服务器时间不一致,那么这个缓存机制就存在问题。

    Cache-Control可以避免这个问题,Cache-Control设置了一个max-age值,表示经过多长时间之后过期。(Cache-Control的优先级高于Expires

    var handle = function (req, res) {
        fs.readFile(filename, function(err, file) {
            res.setHeader("Cache-Control", "max-age=" + 10 * 365 * 24 * 60 * 60 * 1000);
            res.writeHead(200, "Ok");
            res.end(file);
        });
    };
    • 清除缓存

    我们设置缓存可以节省带宽,但是也会带来新的问题,如果文件内容发生变化,怎么通知用户去更新呢?

    1. 日期时间版本号:http://example.com?v=20170223
    2. 文件内容hash值: http://example.com?v=bahbdhjsdjs
  • 相关阅读:
    Sublime Text 3 快捷键精华版
    css动画+滚动的+飞舞的小球
    css动画+照片清晰度动画
    simhash
    抛弃IIS,利用FastCGI让Asp.net与Nginx在一起
    不逃离WIndows,Asp.Net就只能写写进销存管理系统
    吸引下百度蜘蛛
    Arcpy功能总结
    英雄杀
    NCEP Datasets
  • 原文地址:https://www.cnblogs.com/MissFelicia/p/6434157.html
Copyright © 2020-2023  润新知