【HTTP緩存】一步一步打造自己的靜態(tài)web服務(wù)器

占位占位

時間:2016-12-12 23:01:08
學(xué)習(xí)了理論的知識澎迎,還是需要實踐來加深對HTTP緩存的理解。 【這里占個位置球凰,告訴自己要去實踐一下】

更新時間:2016-12-14 15:04:34

一凛膏、教程

  1. 《用NodeJs打造你的靜態(tài)文件服務(wù)器》

【推薦】根據(jù)教程一步一步敲出來,大大加深了對緩存的理解熊经,也知道實際中該如何使用泽艘。

二、采用技術(shù)以及緩存應(yīng)用學(xué)習(xí)

采用NodeJs的 http镐依,url匹涮,fs,path馋吗,zlib 實現(xiàn)一個簡單的web服務(wù)器焕盟,支持強(qiáng)緩存,協(xié)商緩存,GZip壓縮脚翘。

1. 強(qiáng)緩存 灼卢, 協(xié)商緩存

  • 強(qiáng)緩存主要是通過設(shè)置 Response 的Expires 和 Cache-Control`

  • 協(xié)商緩存主要是設(shè)置Response 返回 Last-Modified, 瀏覽器請求資源的時候来农,會把這個值放在 If-Modified-Since 的Header里面鞋真,然后這里判斷是否過時了。

  • 協(xié)商緩存還有一個ETag可以配置使用沃于,但是ETag需要這里生成唯一的資源標(biāo)識涩咖,然后返回給瀏覽器,瀏覽器再次請求一個資源的時候繁莹,會帶上這個ETag標(biāo)記檩互,放在 Request的 If-None-Match 的 header字段,如果文件沒有被修改咨演,則返回304 闸昨,瀏覽器采用本地緩存。

2. 既生Last-Modified何生Etag薄风?

你可能會覺得使用Last-Modified已經(jīng)足以讓瀏覽器知道本地的緩存副本是否足夠新饵较,為什么還需要Etag(實體標(biāo)識)呢?HTTP1.1中Etag的出現(xiàn)主要是為了解決幾個Last-Modified比較難解決的問題:

  • Last-Modified標(biāo)注的最后修改只能精確到秒級遭赂,如果某些文件在1秒鐘以內(nèi)循诉,被修改多次的話,它將不能準(zhǔn)確標(biāo)注文件的修改時間

  • 如果某些文件會被定期生成撇他,當(dāng)有時內(nèi)容并沒有任何變化茄猫,但Last-Modified卻改變了,導(dǎo)致文件沒法使用緩存

  • 有可能存在服務(wù)器沒有準(zhǔn)確獲取文件修改時間逆粹,或者與代理服務(wù)器時間不一致等情形

Etag是服務(wù)器自動生成或者由開發(fā)者生成的對應(yīng)資源在服務(wù)器端的唯一標(biāo)識符募疮,能夠更加準(zhǔn)確的控制緩存。Last-Modified與ETag是可以一起使用的僻弹,服務(wù)器會優(yōu)先驗證ETag阿浓,一致的情況下,才會繼續(xù)比對Last-Modified蹋绽,最后才決定是否返回304芭毙。

3. 瀏覽器行為

  • 在按CMD+R刷新瀏覽器的時候,一直沒有看到使用緩存卸耘,莫名其妙的退敦,后面發(fā)現(xiàn)是 按刷新的時候,跳過了強(qiáng)緩存蚣抗,協(xié)商緩存會驗證侈百。
  • CTRL+CMD+R 跳過 強(qiáng)緩存 和 協(xié)商緩存
  • 只有瀏覽器地址欄,輸入地址,或者頁面超鏈接跳轉(zhuǎn)钝域,采用使用強(qiáng)緩存驗證

三讽坏、代碼

根據(jù)教程一步一步自己敲出來更好。

//config.js
exports.Expires = {
  fileMatch: /^(gif|png|jpg|js|css)$/ig,
  maxAge: 60 * 60 * 24 * 365
}
exports.Compress = {
  match: /css|js|html/ig
}

//MIME.js
// Header 的  Content-Type 
exports.types = {
  "css": "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"
};
//index.js
var PORT = 9999
var http = require('http')
var url = require('url')
var fs = require('fs')
var path = require('path')
var zlib = require("zlib")

var MIME = require('./MIME.js').types
var config = require('./config.js')

var server = http.createServer(function (request, response) {
  // 獲取資源路徑
  var pathname = url.parse(request.url).pathname
  var realPath = 'assets' + pathname

  fs.exists(realPath, function (exists) {
    if (!exists) {
      response.writeHead(404, { 'Content-Type': 'text/plain' })
      response.write('This Request Url ' + pathname + ' was not found on this server')
      response.end()
    } else {
      fs.readFile(realPath, 'binary', function (err, file) {
        if (err) {
          response.writeHead(500, { 'Content-Type': 'text/plain' })
          response.end(err.Error)
        } else {
          var ext = path.extname(realPath)
          ext = ext ? ext.slice(1) : 'unknown'
          var contentType = MIME[ext] || 'text/plain'

          //設(shè)置強(qiáng)緩存 Expires   Cache-Control
          var expires = new Date()
          expires.setTime(expires.getTime() + config.Expires.maxAge * 1000)
          response.setHeader('Expires', expires.toUTCString())
          response.setHeader('Cache-Control', 'max-age=' + config.Expires.maxAge)


          //設(shè)置協(xié)商緩存  Last-Modified   If-Modified-Since   Tag  If-None-Match
          fs.stat(realPath, function (err, stat) {
            var lastModified = stat.mtime.toUTCString()
            response.setHeader("Last-Modified", lastModified)
            if (request.headers["If-Modified-Since"] && lastModified == request.headers["If-Modified-Since"]) {
              response.writeHead(304, "Not Modified")
              response.end()
            } else {

              //使用GZIP壓縮資源   利用Node的 zlib 壓縮
              var raw = fs.createReadStream(realPath)
              var acceptEncoding = request.headers['accept-encoding'] || ""
              var matched = ext.match(config.Compress.match)

              if (matched && acceptEncoding.match(/\bgzip\b/)) {
                response.writeHead(200, "Ok", { 'Content-Encoding': 'gzip' });
                raw.pipe(zlib.createGzip()).pipe(response);
              } else if (matched && acceptEncoding.match(/\bdeflate\b/)) {
                response.writeHead(200, "Ok", { 'Content-Encoding': 'deflate' });
                raw.pipe(zlib.createDeflate()).pipe(response);
              } else {
                response.writeHead(200, { 'Content-Type': contentType })
                raw.pipe(response);
              }
            }
          })
          console.log('load assets file:' + realPath)
        }
      })
    }
  })
})

server.listen(PORT)

console.log('Server runing at port:' + PORT + '...')


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末例证,一起剝皮案震驚了整個濱河市路呜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌织咧,老刑警劉巖胀葱,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異笙蒙,居然都是意外死亡抵屿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門手趣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晌该,“玉大人肥荔,你說我怎么就攤上這事绿渣。” “怎么了燕耿?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵中符,是天一觀的道長。 經(jīng)常有香客問我誉帅,道長淀散,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任蚜锨,我火速辦了婚禮档插,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亚再。我一直安慰自己郭膛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布氛悬。 她就那樣靜靜地躺著则剃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪如捅。 梳的紋絲不亂的頭發(fā)上棍现,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音镜遣,去河邊找鬼己肮。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谎僻。 我是一名探鬼主播窖剑,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼戈稿!你這毒婦竟也來了西土?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鞍盗,失蹤者是張志新(化名)和其女友劉穎需了,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體般甲,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肋乍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了敷存。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墓造。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖锚烦,靈堂內(nèi)的尸體忽然破棺而出觅闽,到底是詐尸還是另有隱情,我是刑警寧澤涮俄,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布蛉拙,位于F島的核電站,受9級特大地震影響彻亲,放射性物質(zhì)發(fā)生泄漏孕锄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一苞尝、第九天 我趴在偏房一處隱蔽的房頂上張望畸肆。 院中可真熱鬧,春花似錦宙址、人聲如沸轴脐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豁辉。三九已至,卻和暖如春舀患,著一層夾襖步出監(jiān)牢的瞬間徽级,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工聊浅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留餐抢,地道東北人现使。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像旷痕,于是被迫代替她去往敵國和親碳锈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容