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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM