成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

深入node.js-瀏覽器緩存機(jī)制

Stardustsky / 1021人閱讀

摘要:瀏覽器緩存的使用是提高用戶體驗(yàn)的一個(gè)重要途徑,通常也是優(yōu)化前端的一種重要方式。瀏覽器看到就會(huì)去讀取緩存信息并呈現(xiàn)。

瀏覽器緩存
瀏覽器緩存(Browser Caching)是為了節(jié)約網(wǎng)絡(luò)的資源加速瀏覽,瀏覽器在用戶磁盤上對(duì)最近請(qǐng)求過的文檔進(jìn)行存儲(chǔ),當(dāng)訪問者再次請(qǐng)求這個(gè)頁面時(shí),瀏覽器就可以從本地磁盤顯示文檔,這樣就可以加速頁面的閱覽。

瀏覽器緩存的使用是提高用戶體驗(yàn)的一個(gè)重要途徑,通常也是優(yōu)化前端的一種重要方式。利用好了緩存可以加快頁面的瀏覽,降低服務(wù)器的壓力,減少網(wǎng)絡(luò)損耗等功能。

瀏覽器緩存分類

協(xié)商緩存

強(qiáng)制緩存

協(xié)商緩存

通過上圖分析:

客戶端向服務(wù)器請(qǐng)求資源

驗(yàn)證標(biāo)識(shí),如果標(biāo)識(shí)通過了驗(yàn)證,則會(huì)響應(yīng)304,告知瀏覽器讀取緩存

如果沒有標(biāo)識(shí),或驗(yàn)證沒有通過,則返回請(qǐng)求的資源

看到這里可能有人會(huì)有問題,標(biāo)識(shí)是什么?
標(biāo)識(shí)主要是用來標(biāo)識(shí)請(qǐng)求的資源是否被修改或更新過,通過請(qǐng)求頭發(fā)送給服務(wù)器進(jìn)行驗(yàn)證。

協(xié)商緩存的標(biāo)識(shí)有兩種:

ETag

Last-Modified

下面我們來講講這兩者的區(qū)別以及用法

Last-Modified

last-modified 根據(jù)詞義就可以知道表示該資源的最后修改時(shí)間。

客戶端第一次請(qǐng)求服務(wù)器,服務(wù)器會(huì)把該資源的最后修改時(shí)間通過響應(yīng)頭返回給客戶端

客戶端再次請(qǐng)求服務(wù)器的時(shí)候,如果在響應(yīng)頭中有Last-Modified字段,瀏覽器就會(huì)在請(qǐng)求頭中加上if-Modified-Since字段給服務(wù)器。

服務(wù)器拿到該字段的值,與該資源的最后修改時(shí)間進(jìn)行對(duì)比,如果相等則說明資源沒有被修改,向客戶端返回304。

瀏覽器看到304就會(huì)去讀取緩存信息并呈現(xiàn)。

下面根據(jù)以上的幾個(gè)點(diǎn),來看看代碼怎么實(shí)現(xiàn):

    const http = require("http");
    const url = require("url");
    const path = require("path");
    const fs = require("fs");
    const mime = require("mime");
    
    const server = http.createServer((req, res) => {
      // 獲取文件名
      const { pathname } = url.parse(req.url, true);
      // 獲取文件路徑
      const filepath = path.join(__dirname, pathname);
    
      /**
       * 判斷文件是否存在
       */
      fs.stat(filepath, (err, stat) => {
        if (err) {
          res.end("not found");
        } else {
          // 獲取if-modified-since這個(gè)請(qǐng)求頭
          const ifModifiedSince = req.headers["if-modified-since"];
          // 獲取資源最后修改時(shí)間
          let lastModified = stat.ctime.toGMTString();
          // 驗(yàn)證資源是否被修改過,如果相同則返回304讓瀏覽器讀取緩存
          if (ifModifiedSince === lastModified) {
            res.writeHead(304);
            res.end();
          }
          // 緩存沒有通過則返回資源,并加上 last-modified響應(yīng)頭,下次瀏覽器就會(huì)在請(qǐng)求頭中帶著 if-modified-since
          else {
            res.setHeader("Content-Type", mime.getType(filepath));
            res.setHeader("Last-Modified", stat.ctime.toGMTString());
            fs.createReadStream(filepath).pipe(res);
          }
        }
      });
    });
    
    server.listen(8000, () => {
      console.log("listen to 8000 port");
    });
    
ETag

ETag它的流程和last-modified是一樣的,僅僅只是驗(yàn)證方式不同,last-modified是取的當(dāng)前請(qǐng)求資源的最后修改時(shí)間來作為驗(yàn)證,而ETag則是對(duì)當(dāng)前請(qǐng)求的資源做一個(gè)唯一的標(biāo)識(shí)。

標(biāo)識(shí)可以是一個(gè)字符串,文件的size,hash等等,只要能夠合理標(biāo)識(shí)資源的唯一性并能驗(yàn)證是否修改過就可以了。比如讀取文件內(nèi)容,將文件內(nèi)容轉(zhuǎn)換成一個(gè)hash值,每次接收到客戶端發(fā)送過來的時(shí)候,重新讀取文件轉(zhuǎn)成hash值,與之前的做對(duì)比,看資源是否修改過。

和Last-Modify相同,服務(wù)器在響應(yīng)頭返回一個(gè)ETag字段,那么請(qǐng)求的時(shí)候就會(huì)在請(qǐng)求頭中加入if-none-match

下面來看看代碼,代碼中我都會(huì)加入詳細(xì)的注釋:

const http = require("http");
const url = require("url");
const path = require("path");
const fs = require("fs");
const mime = require("mime");
const crypto = require("crypto");

const server = http.createServer(function(req, res) {
  // 獲取請(qǐng)求的資源名稱
  let { pathname } = url.parse(req.url, true);
  // 獲取文件路徑
  let filepath = path.join(__dirname, pathname);

  /**
   * 判斷文件是否存在
   */
  fs.stat(filepath, (err, stat) => {
    if (err) {
      return sendError(req, res);
    } else {
      let ifNoneMatch = req.headers["if-none-match"];
      let readStream = fs.createReadStream(filepath);
      let md5 = crypto.createHash("md5");

      // 通過流的方式讀取文件并且通過md5進(jìn)行加密,相當(dāng)于轉(zhuǎn)成一個(gè)hash字符串作為etag的值
      readStream.on("data", function(data) {
        md5.update(data);
      });
      readStream.on("end", function() {
        let etag = md5.digest("hex");
        // 驗(yàn)證etag,判斷資源是否被修改過,如果沒有則返回304
        if (ifNoneMatch === etag) {
          res.writeHead(304);
          res.end();
        } else {
          res.setHeader("Content-Type", mime.getType(filepath));
          // 第一次服務(wù)器返回的時(shí)候,會(huì)把文件的內(nèi)容算出來一個(gè)標(biāo)識(shí),發(fā)給客戶端
          fs.readFile(filepath, (err, content) => {
            // 客戶端看到etag之后,也會(huì)把此標(biāo)識(shí)保存在客戶端,下次再訪問服務(wù)器的時(shí)候,發(fā)給服務(wù)器
            res.setHeader("Etag", etag);
            fs.createReadStream(filepath).pipe(res);
          });
        }
      });
    }
  });
});
server.listen(8000, () => {
  console.log("listen to 8000 port");
});
強(qiáng)制緩存

通過上圖分析:

強(qiáng)制緩存通過Cache-Control這個(gè)響應(yīng)頭中的max-age:60(緩存60s)來判斷緩存是否過期

如果過期了則重新向服務(wù)器請(qǐng)求資源

如果沒有過期,則不經(jīng)過服務(wù)器,直接讀取資源

強(qiáng)制緩存比較簡(jiǎn)單,直接看一下代碼的實(shí)現(xiàn)

    const http = require("http");
    const url = require("url");
    const path = require("path");
    const fs = require("fs");
    const mime = require("mime");
    
    const server = http.createServer(function(req, res) {
      let { pathname } = url.parse(req.url, true);
      let filepath = path.join(__dirname, pathname);
      fs.stat(filepath, (err, stat) => {
        if (err) {
          res.setHeader("Content-Type", mime.getType(filepath));
          // 設(shè)置緩存過期時(shí)間
          res.setHeader("Cache-Control", "max-age=100");
          fs.createReadStream(filepath).pipe(res);
        } else {
          return send(req, res, filepath);
        }
      });
    });
    server.listen(8000, () => {
      console.log("listen to port 8000");
    });

強(qiáng)制緩存就是向?yàn)g覽器設(shè)置一個(gè)過期時(shí)間例如cache-control:max-age=60表示這是一個(gè)60秒的過期時(shí)間,60秒以內(nèi)瀏覽器都會(huì)從緩存讀取該資源,超過60秒則訪問服務(wù)器

cache-control還有另外幾個(gè)值可以設(shè)置

private 客戶端可以緩存

public 客戶端和代理服務(wù)器都可以緩存

max-age=60 緩存內(nèi)容將在60秒后失效

no-cache 需要使用對(duì)比緩存驗(yàn)證數(shù)據(jù),強(qiáng)制向源服務(wù)器再次驗(yàn)證

no-store 所有內(nèi)容都不會(huì)緩存,強(qiáng)制緩存和對(duì)比緩存都不會(huì)觸發(fā)

總結(jié)

理解緩存對(duì)前端開發(fā)來說十分的重要,這也是為何把這篇文章寫出來的原因,后續(xù)會(huì)繼續(xù)為大家?guī)韓ode相關(guān)的文章,如果寫錯(cuò)或不好的地方希望大家指出來,如果覺得寫的還行,麻煩點(diǎn)個(gè)贊哈!

以下我的新個(gè)人微信公眾號(hào),也會(huì)為大家持續(xù)提供原創(chuàng)文章,歡迎大家關(guān)注,如果用戶量足夠,會(huì)在里面為大家提供一些項(xiàng)目類的視頻教程,謝謝

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/108931.html

相關(guān)文章

  • 深入淺出node.js總結(jié)-模塊機(jī)制(1)

    摘要:先天就缺乏一項(xiàng)功能模塊通過標(biāo)簽引入代碼的方式顯得雜亂無章,語言自身毫無組織和約束能力。與文件模塊區(qū)別地方在于它從內(nèi)存中加載緩存執(zhí)行結(jié)果的位置核心模塊在對(duì)象上,文件模塊在對(duì)象上未完待續(xù) javascript先天就缺乏一項(xiàng)功能:模塊 javasciprt 通過script標(biāo)簽引入代碼的方式顯得雜亂無章,語言自身毫無組織和約束能力。人們不得不用命名空間等方式人為地約束代碼,以求達(dá)到安全和易用的...

    jifei 評(píng)論0 收藏0
  • 前端基礎(chǔ)

    摘要:談起閉包,它可是兩個(gè)核心技術(shù)之一異步基于打造前端持續(xù)集成開發(fā)環(huán)境本文將以一個(gè)標(biāo)準(zhǔn)的項(xiàng)目為例,完全拋棄傳統(tǒng)的前端項(xiàng)目開發(fā)部署方式,基于容器技術(shù)打造一個(gè)精簡(jiǎn)的前端持續(xù)集成的開發(fā)環(huán)境。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥,不論是面試求職,還是日...

    graf 評(píng)論0 收藏0
  • node核心特性理解

    摘要:概述本文主要介紹了我對(duì)的一些核心特性的理解,包括架構(gòu)特點(diǎn)機(jī)制核心模塊與簡(jiǎn)單應(yīng)用。在此期間,主線程繼續(xù)執(zhí)行其他任務(wù)。延續(xù)了瀏覽器端單線程,只用一個(gè)主線程執(zhí)行,不斷循環(huán)遍歷事件隊(duì)列,執(zhí)行事件。 原文地址在我的博客,轉(zhuǎn)載請(qǐng)注明來源,謝謝! node是在前端領(lǐng)域經(jīng)??吹降脑~。node對(duì)于前端的重要性已經(jīng)不言而喻,掌握node也是作為合格的前端工程師一項(xiàng)基本功了。知道node、知道后端的一些東西...

    huangjinnan 評(píng)論0 收藏0
  • Node.js入門:模塊機(jī)制

    摘要:模塊載入策略的模塊分為兩類,一類為原生核心模塊,一類為文件模塊。最后傳入對(duì)象的,方法,,文件名,目錄名作為實(shí)參并執(zhí)行。在這個(gè)主文件中,可以通過方法去引入其余的模塊。以上所描述的模塊載入機(jī)制均定義在中。 CommonJS規(guī)范? 早在Netscape誕生不久后,JavaScript就一直在探索本地編程的路,Rhino是其代表產(chǎn)物。無奈那時(shí)服務(wù)端JavaScript走的路均是參考眾多服務(wù)器端...

    alanoddsoff 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<