二十四.瀏覽器的協商快取與伺服器的自啟動
阿新 • • 發佈:2021-06-10
- 概述
協商快取: 1. 客戶端向服務端傳送一個請求,請求相應的資源 2. 服務端向客戶端傳送一個響應,在響應頭中攜帶兩個關於快取的資訊,分別是 當前檔案的唯一標識(eTag)和 當前檔案的最後一次修改時間(last-modified) 3. 客戶端收到了響應檔案和關於檔案的快取資訊,並把快取資訊儲存在客戶端,但是更換了名稱,把eTag更名為if-none-match,把last-modified更名為if-modified-since。 4. 客戶端第二次請求服務端,請求相應的資源,會在請求頭上攜帶兩個欄位,就是之前已經請求過的檔案的快取資訊 if-none-match和if-modified-since 5. 服務端接收到了客戶端的if-none-match和if-modified-since,然後會重新獲取被請求檔案的eTag和last-modified,然後開始比較,如果兩個都比較成功,則讀取快取,否則返回新的響應 6.如果走快取,則服務端的響應狀態碼是304,並且不需要設定任何的響應內容 7.如果走快取,則客戶端接收到的狀態碼是304,並直接去讀取快取 8.如果不走快取,則響應狀態碼是200,並且響應最新的資料,還要攜帶最新的eTag和last-modified
- web頁面如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> </head> <body> <h1>協商快取</h1> <ul> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> </ul> </body> </html>
- 協商快取與伺服器的自啟動
const express = require("express"); const { exec } = require("child_process") const path = require("path"); const etag = require("etag"); const { promisify } = require("util"); const fs = require("fs"); const { resolve6 } = require("dns"); const app = express(); app.get("/", async (req, res) => { // sendFile已經把協商快取設定好了 /* const filePath = path.resolve(__dirname, "./index.html"); res.sendFile(filePath) */ //在接收請求的時候,先獲取請求頭攜帶的if-none-match 和 if-modified-since const ifNoneMatch = req.headers["if-none-match"]; const ifModifiedSince = req.headers["if-modified-since"]; console.log(ifNoneMatch, ifModifiedSince); const filePath = path.resolve(__dirname, "./index.html"); const rs = fs.createReadStream(filePath); //fs有一個stat方法 可以得到檔案的詳細資訊 //使用promisify方法把stat方法包裝成promise物件 const stat = promisify(fs.stat); //得到檔案詳細的資訊 const fileDetail = await stat(filePath); // console.log(fileDetail); //得到檔案的最後修改時間 const fileTime = fileDetail.mtime.toGMTString(); //得到檔案的唯一標識 const fileEtag = etag(fileDetail); // console.log(fileTime.toString(), fileEtag); //協商快取判斷 if (ifNoneMatch === fileEtag && ifModifiedSince === fileTime) { return res.status(304).end() } //把檔案的唯一標識和最後修改時間設定在響應頭中 res.set("ETag", fileEtag); res.set("Last-Modified", fileTime); rs.pipe(res); }) app.listen("3000", (err) => { if (err) { console.log(err); return; } console.log("服務已經啟動 http://127.0.0.1:3000"); // exec("start http://127.0.0.1:3000") })