摘要:瀏覽器緩存的使用是提高用戶體驗的一個重要途徑,通常也是優化前端的一種重要方式。瀏覽器看到就會去讀取緩存信息并呈現。
瀏覽器緩存
瀏覽器緩存(Browser Caching)是為了節約網絡的資源加速瀏覽,瀏覽器在用戶磁盤上對最近請求過的文檔進行存儲,當訪問者再次請求這個頁面時,瀏覽器就可以從本地磁盤顯示文檔,這樣就可以加速頁面的閱覽。
瀏覽器緩存的使用是提高用戶體驗的一個重要途徑,通常也是優化前端的一種重要方式。利用好了緩存可以加快頁面的瀏覽,降低服務器的壓力,減少網絡損耗等功能。
瀏覽器緩存分類協商緩存
強制緩存
協商緩存通過上圖分析:
客戶端向服務器請求資源
驗證標識,如果標識通過了驗證,則會響應304,告知瀏覽器讀取緩存
如果沒有標識,或驗證沒有通過,則返回請求的資源
看到這里可能有人會有問題,標識是什么?
標識主要是用來標識請求的資源是否被修改或更新過,通過請求頭發送給服務器進行驗證。
協商緩存的標識有兩種:
ETag
Last-Modified
下面我們來講講這兩者的區別以及用法
Last-Modifiedlast-modified 根據詞義就可以知道表示該資源的最后修改時間。
客戶端第一次請求服務器,服務器會把該資源的最后修改時間通過響應頭返回給客戶端
客戶端再次請求服務器的時候,如果在響應頭中有Last-Modified字段,瀏覽器就會在請求頭中加上if-Modified-Since字段給服務器。
服務器拿到該字段的值,與該資源的最后修改時間進行對比,如果相等則說明資源沒有被修改,向客戶端返回304。
瀏覽器看到304就會去讀取緩存信息并呈現。
下面根據以上的幾個點,來看看代碼怎么實現:
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這個請求頭 const ifModifiedSince = req.headers["if-modified-since"]; // 獲取資源最后修改時間 let lastModified = stat.ctime.toGMTString(); // 驗證資源是否被修改過,如果相同則返回304讓瀏覽器讀取緩存 if (ifModifiedSince === lastModified) { res.writeHead(304); res.end(); } // 緩存沒有通過則返回資源,并加上 last-modified響應頭,下次瀏覽器就會在請求頭中帶著 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是一樣的,僅僅只是驗證方式不同,last-modified是取的當前請求資源的最后修改時間來作為驗證,而ETag則是對當前請求的資源做一個唯一的標識。
標識可以是一個字符串,文件的size,hash等等,只要能夠合理標識資源的唯一性并能驗證是否修改過就可以了。比如讀取文件內容,將文件內容轉換成一個hash值,每次接收到客戶端發送過來的時候,重新讀取文件轉成hash值,與之前的做對比,看資源是否修改過。
和Last-Modify相同,服務器在響應頭返回一個ETag字段,那么請求的時候就會在請求頭中加入if-none-match
下面來看看代碼,代碼中我都會加入詳細的注釋:
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) { // 獲取請求的資源名稱 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進行加密,相當于轉成一個hash字符串作為etag的值 readStream.on("data", function(data) { md5.update(data); }); readStream.on("end", function() { let etag = md5.digest("hex"); // 驗證etag,判斷資源是否被修改過,如果沒有則返回304 if (ifNoneMatch === etag) { res.writeHead(304); res.end(); } else { res.setHeader("Content-Type", mime.getType(filepath)); // 第一次服務器返回的時候,會把文件的內容算出來一個標識,發給客戶端 fs.readFile(filepath, (err, content) => { // 客戶端看到etag之后,也會把此標識保存在客戶端,下次再訪問服務器的時候,發給服務器 res.setHeader("Etag", etag); fs.createReadStream(filepath).pipe(res); }); } }); } }); }); server.listen(8000, () => { console.log("listen to 8000 port"); });強制緩存
通過上圖分析:
強制緩存通過Cache-Control這個響應頭中的max-age:60(緩存60s)來判斷緩存是否過期
如果過期了則重新向服務器請求資源
如果沒有過期,則不經過服務器,直接讀取資源
強制緩存比較簡單,直接看一下代碼的實現
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)); // 設置緩存過期時間 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"); });
強制緩存就是向瀏覽器設置一個過期時間例如cache-control:max-age=60表示這是一個60秒的過期時間,60秒以內瀏覽器都會從緩存讀取該資源,超過60秒則訪問服務器
cache-control還有另外幾個值可以設置
private 客戶端可以緩存
public 客戶端和代理服務器都可以緩存
max-age=60 緩存內容將在60秒后失效
no-cache 需要使用對比緩存驗證數據,強制向源服務器再次驗證
no-store 所有內容都不會緩存,強制緩存和對比緩存都不會觸發
總結理解緩存對前端開發來說十分的重要,這也是為何把這篇文章寫出來的原因,后續會繼續為大家帶來node相關的文章,如果寫錯或不好的地方希望大家指出來,如果覺得寫的還行,麻煩點個贊哈!
以下我的新個人微信公眾號,也會為大家持續提供原創文章,歡迎大家關注,如果用戶量足夠,會在里面為大家提供一些項目類的視頻教程,謝謝
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/108931.html
摘要:先天就缺乏一項功能模塊通過標簽引入代碼的方式顯得雜亂無章,語言自身毫無組織和約束能力。與文件模塊區別地方在于它從內存中加載緩存執行結果的位置核心模塊在對象上,文件模塊在對象上未完待續 javascript先天就缺乏一項功能:模塊 javasciprt 通過script標簽引入代碼的方式顯得雜亂無章,語言自身毫無組織和約束能力。人們不得不用命名空間等方式人為地約束代碼,以求達到安全和易用的...
摘要:概述本文主要介紹了我對的一些核心特性的理解,包括架構特點機制核心模塊與簡單應用。在此期間,主線程繼續執行其他任務。延續了瀏覽器端單線程,只用一個主線程執行,不斷循環遍歷事件隊列,執行事件。 原文地址在我的博客,轉載請注明來源,謝謝! node是在前端領域經常看到的詞。node對于前端的重要性已經不言而喻,掌握node也是作為合格的前端工程師一項基本功了。知道node、知道后端的一些東西...
摘要:模塊載入策略的模塊分為兩類,一類為原生核心模塊,一類為文件模塊。最后傳入對象的,方法,,文件名,目錄名作為實參并執行。在這個主文件中,可以通過方法去引入其余的模塊。以上所描述的模塊載入機制均定義在中。 CommonJS規范? 早在Netscape誕生不久后,JavaScript就一直在探索本地編程的路,Rhino是其代表產物。無奈那時服務端JavaScript走的路均是參考眾多服務器端...
閱讀 3558·2021-11-22 11:59
閱讀 955·2021-09-27 13:36
閱讀 3617·2021-09-24 09:47
閱讀 2266·2021-09-01 11:39
閱讀 985·2021-08-31 09:37
閱讀 2317·2021-08-05 10:01
閱讀 1682·2019-08-30 15:55
閱讀 705·2019-08-30 15:54