node.js的學習(三) http緩存原理

http 緩存

瀏覽器緩存的做用

合理使用瀏覽器的緩存,能夠有效的減小請求的訪問次數,一個是減少服務器壓力,更重要的是可以下降頁面的加載時間。html

搭建緩存基本測試環境

function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     console.log('111')
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
     console.log('222')
     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服務建立成功")
})
複製代碼

強緩存

  1. http1.0中 Expires 字段。控制多少秒後資源過時
function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
     res.setHeader('Expires',new Date(Date.now()+10*1000).toUTCString())
     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服務建立成功")
})
複製代碼

當請求資源的時候,會把客戶端的時間和expires的時間進行對比,若是大於該時間,就過時,不然就直接使用該緩存資源
可是存在一個問題。客戶端的時間是能夠自行修改的,或者存在客戶端的時間和服務端的時間不一致,因此不必定知足預期的效果後端

針對上述問題 2. 在http1.1 中 使用 Cache-Control瀏覽器

function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
     res.setHeader('Expires',new Date(Date.now()+10*1000).toUTCString())
     res.setHeader('Cache-Control','max-age=20')
     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服務建立成功")
})
複製代碼

Cache-Control 是優先級別高於 Expires緩存

協商緩存

上述的expires和cache-control都會訪問本地緩存直接驗證看是否過時,若是沒過時就走緩存,而且返回200。
可是若是設置了no-cache和no-store就會忽略本地緩存,會去請求服務器資源是否更新,若是沒有更新就繼續使用本地緩存,此時返回304,着就是協商緩存,協商緩存的主要包括last-modified和etag
協商緩存就是在瀏覽器和服務器中是否作緩存進行協商,若是協商的結果是須要更新,就會返回200並更新內容,若是不須要,就返回304,不返回內容,雖而後端仍然要應答,可是不用生成內容,也不用傳輸內容。服務器

  1. 根據時間
function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
    //  res.setHeader('Expires',new Date(Date.now()+10*1000).toUTCString())
    //  res.setHeader('Cache-Control','max-age=20')
    res.setHeader('Cache-Control','no-cache')  // 不走強緩存
    res.setHeader('last-modified',new Date().toUTCString())
    if( new Date(req.headers['if-modified-since']).getTime()+3*1000>Date.now()){
        console.log("協商緩存命中")
        res.statusCode=304
        res.end()
        return 
    }

     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服務建立成功")
})
複製代碼
  1. 根據內容hash 利用Etag
function updateTime() {
  this.timer=this.timer||  setInterval(()=>{
        this.time = new Date().toUTCString()
    },5000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
    const content = ` 
    document.writeln('<br> JS update time : ${updateTime()}')
 `
    res.setHeader('Cache-Control','no-cache')  // 不走強緩存
   const crypto = require('crypto')
   const hash = crypto.createHash('sha1').update(content).digest('hex')
   res.setHeader('Etag',hash)
   if(req.headers['if-none-match']===hash){
       console.log('緩存命中')
       res.statusCode = 304
       res.end()
       return 
   }

    
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服務建立成功")
})
複製代碼
相關文章
相關標籤/搜索