摘要:概念緩存是一種保存資源副本并在下次請求時直接使用該副本的技術。緩存能緩解服務器壓力,提高響應速度,提升用戶體驗。以下討論的緩存是針對對資源而言的,且緩存策略都是依靠報文的首部來實現。參考緩存控制小結淺談瀏覽器的緩存機制
概念
緩存是一種保存資源副本并在下次請求時直接使用該副本的技術。——MDN
緩存能緩解服務器壓力,提高響應速度,提升用戶體驗。
以下討論的緩存是針對對img/script/css資源而言的,且緩存策略都是依靠 http 報文的首部來實現。
實驗 搭建實驗環境編寫 html 文件
緩存 緩存實驗
服務端代碼
const path = require("path") const url = require("url") const fs = require("fs") const zlib = require("zlib") const img = fs.readFileSync(path.resolve(__dirname, "./static/sun.jpg"), "binary") http.createServer((req, res) => { const html = fs.createReadStream(path.resolve(__dirname, "./static/index.html")) let { pathname } = url.parse(req.url) if (pathname === "/") { res.writeHead(200, { "Content-Type": "text/html", "Content-Encoding": "gzip" }) html.pipe(zlib.createGzip()).pipe(res) } else if (pathname === "/sun.jpg") { res.writeHead(200, { "Content-Type": "image/jpeg" }) res.write(img, "binary") res.end() } else { res.end(pathname) } }).listen(3210)
訪問 http://localhost:3210 , 看到相應的文檔和圖片,且無論刷新多少次,sun.jpg 的 Status 和 Size 都不變。控制臺里勾選 Preserve log
Cache-Control通過在服務端設置相應首部 Cache-Control 可以控制緩存行為,例如
Cache-Control: no-cache, 告訴瀏覽器,下次請求該資源時,不直接使用緩存,而是向服務端發送請求,服務端會根據請求,判斷本地的資源是否過期
Cache-Control: no-store, 告訴瀏覽器,不要緩存該資源
Cache-Control: max-age=age, 告訴瀏覽器,這個資源有效的時長 age,在該時間范圍內,如果需要該資源,直接從本地取,不要煩我(向我發送請求)
修改服務端代碼設置圖片緩存時長 30s
res.writeHead(200, { "Content-Type": "image/jpeg", "Cache-Control": "max-age=30" })
快速刷新頁面2次,超過30s后,再刷新一次
三次刷新結果在控制臺顯示的情況如下
其中第二次請求 sun.jpg 的請求情況如下,200 OK (from memory cache),第三次請求 sun.jpg 則又是從服務端獲取圖片,顯示資源 1.6M。
現在的情形是這樣的,30s到了,瀏覽器向服務端發出 sun.jpg 的請求,但服務器并沒有更新該資源,所以服務器告訴瀏覽器,“我沒有修改該資源,你還是用你本地的吧,我就不再發給你了”。這些通過 Last-Modified 和 If-Modified-Since 來實現。
瀏覽器第一次向服務端請求 sun.jpg,服務端不僅返回 sun.jpg,還通過響應首部的 Last-Modified(瀏覽器自動添加),告訴瀏覽器該資源最后修改的時間。
下次瀏覽器再次請求 sun.jpg,會通過請求首部的 If-Modified-Since, 把自己手上這個資源最后修改的時間告訴服務端,服務端通過這個時間,判斷瀏覽器本地的資源是否是最新的,若是,則返回 304(not modified) 和響應頭部即可,不用返回圖片;若不是,則返回 200 和圖片。
修改服務端代碼const http = require("http") const path = require("path") const url = require("url") const fs = require("fs") const zlib = require("zlib") const img = fs.readFileSync(path.resolve(__dirname, "./static/sun.jpg"), "binary") let date = new Date() let lastModified = date.toUTCString() http.createServer((req, res) => { const html = fs.createReadStream(path.resolve(__dirname, "./static/index.html")) let { pathname } = url.parse(req.url) if (pathname === "/") { res.writeHead(200, { "Content-Type": "text/html", "Content-Encoding": "gzip" }) html.pipe(zlib.createGzip()).pipe(res) } else if (pathname === "/sun.jpg") { if (req.headers["if-modified-since"] === lastModified) { res.writeHead(304, { "Content-Type": "image/jpeg", "Cache-Control": "max-age=30", "Last-Modified": lastModified }) res.end() } else { res.writeHead(200, { "Content-Type": "image/jpeg", "Cache-Control": "max-age=30", "Last-Modified": lastModified }) res.write(img, "binary") res.end() } } else { res.end(pathname) } }).listen(3210)
瀏覽器刷新一次,30s內,再刷新一次,30s后再刷新一次
三次刷新的結果在控制臺里顯示如下,最后一次還有 189B 是服務端響應頭部的大小,178ms 里包含了服務端比較修改時間,返回響應頭部的時間。
且最后一次請求 sun.jpg 的請求情形如下
ETag & If-None-MatchEtag 和 If-None-Match 起到的作用和上文中 Last-Modified 和 If-Modified 差不多,區別在于 Etag 是服務端上通過算法給資源計算出的唯一標示,當資源修改時,該標示會發生變化。服務端通過響應首部 Etag 將該標示告訴瀏覽器,瀏覽器再下一次請求該資源時,會通過請求首部 If-None-Match 帶上該標示,服務端會比較請求中的標示和該資源最新的標示,如果一樣,證明瀏覽器擁有的該資源是最新的,僅返回304和響應頭部,否則返回200和整個資源。
強制刷新常使用的強制刷新就是通過修改請求首部來實現的
將 Cache-Control 和 Pragma 設為 no-cache,去除 If-Modified, If-None-Match
盜個圖,HTTP緩存控制小結 快速更新很多js文件或css文件的文件名會帶有文件指紋或版本號,通過改變文件名,讓瀏覽器以為請求的新的未緩存的資源從而實現快速更新。
參考HTTP緩存控制小結
[淺談瀏覽器http的緩存機制](http://www.cnblogs.com/vajoy/...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/61909.html
摘要:服務器告訴客戶,原來緩沖的文檔還可以繼續使用。不是服務器發出的錯誤提示。如果相同,則獲取本地的緩存信息,反之服務器返回新的資源。服務器靜態資源修改了,返回的,也會修改這個是樂視網首頁第二次請求時的截包,會發現靜態資源的返回基本都是 http 304 好久沒寫了。感覺荒廢了好久。剛好今天有朋友問我關于靜態資源緩存問題。突然喚起我的學習興趣了。發現好多同學對靜態資源都不是很清楚。小弟我剛好...
摘要:服務器告訴客戶,原來緩沖的文檔還可以繼續使用。不是服務器發出的錯誤提示。如果相同,則獲取本地的緩存信息,反之服務器返回新的資源。服務器靜態資源修改了,返回的,也會修改這個是樂視網首頁第二次請求時的截包,會發現靜態資源的返回基本都是 http 304 好久沒寫了。感覺荒廢了好久。剛好今天有朋友問我關于靜態資源緩存問題。突然喚起我的學習興趣了。發現好多同學對靜態資源都不是很清楚。小弟我剛好...
摘要:可以發送通知消息以再次吸引用戶并留住他們。在即時通訊等使用情形中,一條消息可將最多的有效負載傳送至客戶端應用。瀏覽器的的消息推送主要依賴,服務端消息推送傳遞到,然后再由推送到客戶端。 引言 Progressive Web App, 簡稱 PWA,是提升 Web App 的體驗的一種新方法,能給用戶原生應用的體驗。Service Worker 是 PWA 中的重要一部分。Service ...
閱讀 987·2021-11-24 10:30
閱讀 2316·2021-10-08 10:04
閱讀 3949·2021-09-30 09:47
閱讀 1433·2021-09-29 09:45
閱讀 1435·2021-09-24 10:33
閱讀 6234·2021-09-22 15:57
閱讀 2351·2021-09-22 15:50
閱讀 4079·2021-08-30 09:45