<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
無論是開發中或者是面試中,HTTP快取都是非常重要的,這體現在了兩個方面:
所以本篇文章,我不講廢話,我就通過Nodejs的簡單實踐,給大家講最通俗易懂的HTTP快取,大家通過這篇文章一定能瞭解掌握它!!!
npm init
npm i koa -D npm i nodemon -g
<!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> <link rel="stylesheet" href="./static/css/index.css" rel="external nofollow" > </head> <body> <div class="box"> </div> </body> </html>
.box { width: 500px; height: 300px; background-image: url('../image/guang.jpg'); background-size: 100% 100%; color: #000; }
const Koa = require('koa') const fs = require('fs') const path = require('path') const mimes = { css: 'text/css', less: 'text/css', gif: 'image/gif', html: 'text/html', ico: 'image/x-icon', jpeg: 'image/jpeg', jpg: 'image/jpeg', js: 'text/javascript', json: 'application/json', pdf: 'application/pdf', png: 'image/png', svg: 'image/svg+xml', swf: 'application/x-shockwave-flash', tiff: 'image/tiff', txt: 'text/plain', wav: 'audio/x-wav', wma: 'audio/x-ms-wma', wmv: 'video/x-ms-wmv', xml: 'text/xml', } // 獲取檔案的型別 function parseMime(url) { // path.extname獲取路徑中檔案的字尾名 let extName = path.extname(url) extName = extName ? extName.slice(1) : 'unknown' return mimes[extName] } // 將檔案轉成傳輸所需格式 const parseStatic = (dir) => { return new Promise((resolve) => { resolve(fs.readFileSync(dir), 'binary') }) } const app = new Koa() app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // 存取根路徑返回index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) // 設定型別 ctx.set('Content-Type', parseMime(url)) // 設定傳輸 ctx.body = await parseStatic(filePath) } }) app.listen(9898, () => { console.log('start at port 9898') })
現在你可以在終端中輸入nodemon index,看到下方的顯示,則代表成功啟動了服務
此時你可以在瀏覽器連結裡輸入http://localhost:9898/,開啟看到如下頁面,則代表頁面存取成功!!!
HTTP快取常見的有兩類:
強快取:可以由這兩個欄位其中一個決定
協商快取:可以由這兩對欄位中的一對決定
Last-Modified,If-Modified-Since
Etag,If-None-Match(優先順序更高)
接下來我們就開始講強快取
我們只需設定響應頭裡expires的時間為當前時間 + 30s就行了
app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // 存取根路徑返回index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) // 設定型別 ctx.set('Content-Type', parseMime(url)) // 設定 Expires 響應頭 const time = new Date(Date.now() + 30000).toUTCString() ctx.set('Expires', time) // 設定傳輸 ctx.body = await parseStatic(filePath) } })
然後我們在前端頁面重新整理,我們可以看到請求的資源的響應頭裡多了一個expires的欄位
並且,在30s內,我們重新整理之後,看到請求都是走memory,這意味著,通過expires設定強快取的時效是30s,這30s之內,資源都會走本地快取,而不會重新請求
注意點:有時候你Nodejs程式碼更新了時效時間,但是發現前端頁面還是在走上一次程式碼的時效,這個時候,你可以把這個Disabled cache打鉤,然後重新整理一下,再取消打鉤
其實cache-control跟expires效果差不多,只不過這兩個欄位設定的值不一樣而已,前者設定的是秒數,後者設定的是毫秒數
app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // 存取根路徑返回index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) // 設定型別 ctx.set('Content-Type', parseMime(url)) // 設定 Cache-Control 響應頭 ctx.set('Cache-Control', 'max-age=30') // 設定傳輸 ctx.body = await parseStatic(filePath) } })
前端頁面響應頭多了cache-control這個欄位,且30s內都走本地快取,不會去請求伺服器端
與強快取不同的是,強快取是在時效時間內,不走伺服器端,只走本地快取;而協商快取是要走伺服器端的,如果請求某個資源,去請求伺服器端時,發現命中快取則返回304,否則則返回所請求的資源,那怎麼才算命中快取呢?接下來講講
簡單來說就是:
// 獲取檔案資訊 const getFileStat = (path) => { return new Promise((resolve) => { fs.stat(path, (_, stat) => { resolve(stat) }) }) } app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // 存取根路徑返回index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) const ifModifiedSince = ctx.request.header['if-modified-since'] const fileStat = await getFileStat(filePath) console.log(new Date(fileStat.mtime).getTime()) ctx.set('Cache-Control', 'no-cache') ctx.set('Content-Type', parseMime(url)) // 比對時間,mtime為檔案最後修改時間 if (ifModifiedSince === fileStat.mtime.toGMTString()) { ctx.status = 304 } else { ctx.set('Last-Modified', fileStat.mtime.toGMTString()) ctx.body = await parseStatic(filePath) } } })
第一次請求時,響應頭中:
第二次請求時,請求頭中:
由於資源並沒修改,則命中快取,返回304:
此時我們修改一下index.css
.box { width: 500px; height: 300px; background-image: url('../image/guang.jpg'); background-size: 100% 100%; /* 修改這裡 */ color: #333; }
然後我們重新整理一下頁面,index.css變了,所以會沒命中快取,返回200和新資源,而guang.jpg並沒有修改,則命中快取返回304:
其實Etag,If-None-Match跟Last-Modified,If-Modified-Since大體一樣,區別在於:
那我們要怎麼比對資源內容呢?我們只需要讀取資源內容,轉成hash值,前後進行比對就行了!!
const crypto = require('crypto') app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // 存取根路徑返回index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) const fileBuffer = await parseStatic(filePath) const ifNoneMatch = ctx.request.header['if-none-match'] // 生產內容hash值 const hash = crypto.createHash('md5') hash.update(fileBuffer) const etag = `"${hash.digest('hex')}"` ctx.set('Cache-Control', 'no-cache') ctx.set('Content-Type', parseMime(url)) // 對比hash值 if (ifNoneMatch === etag) { ctx.status = 304 } else { ctx.set('etag', etag) ctx.body = fileBuffer } } })
驗證方式跟剛剛Last-Modified,If-Modified-Since的一樣,這裡就不重複說明了。。。
參考 https://www.jb51.net/article/254078.htm
以上就是實踐範例理解js強快取協商快取的詳細內容,更多關於js強快取協商快取的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45