成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【譯】緩存的最佳實(shí)踐以及max-age的陷阱

mist14 / 1102人閱讀

摘要:可能會(huì)延長(zhǎng)這些的壽命假設(shè)你有以下的這個(gè)緩存了和如果命中了緩存,就從緩存中取,否則發(fā)起網(wǎng)絡(luò)請(qǐng)求如果我們更改了,我們會(huì)修改中的版本號(hào),觸發(fā)的更新。

本文翻譯自:https://jakearchibald.com/201...

這是一篇2016年的老文章。作者是Chrome瀏覽器的開(kāi)發(fā)成員。

本文首發(fā)于公眾號(hào):符合預(yù)期的CoyPan

使用正確的緩存可以帶來(lái)巨大的頁(yè)面性能上的收益,節(jié)省帶寬,減少服務(wù)器成本。但是許多網(wǎng)站并沒(méi)有解決好他們的緩存問(wèn)題,創(chuàng)造了一個(gè)race conditions,導(dǎo)致相互依賴的資源之間失去了同步。

絕大多數(shù)緩存的最佳實(shí)踐,都屬于下面兩種模式:

模式一:不可變的內(nèi)容 ,長(zhǎng)時(shí)間的max-age
Cache-Control: max-age = 31536000

同一個(gè)URL對(duì)應(yīng)的內(nèi)容永不改變

瀏覽器/CDN 可以緩存這個(gè)資源長(zhǎng)達(dá)一年的時(shí)間

被緩存資源的存儲(chǔ)時(shí)間小于max-age指定的秒數(shù)時(shí),該資源可以直接被使用而無(wú)需經(jīng)過(guò)服務(wù)器。

在這種模式下,你不會(huì)去改變特定url下的文件內(nèi)容,你直接改變url:



…

每一個(gè)URL都包含一個(gè)跟隨文件內(nèi)容變換的部分。這個(gè)部分可以是版本號(hào),修改日期,或者文件內(nèi)容的hash值。

大多數(shù)服務(wù)端框架都有工具可以簡(jiǎn)單的實(shí)現(xiàn)這個(gè)需求。Node.js下還有更輕量級(jí)的工具能夠做到同樣的事情,比如gulp-rev.

但是,這種模式不適合諸如文章、博客這樣的場(chǎng)景。文章和博客的URL是不會(huì)有版本號(hào)的,而且他們的內(nèi)容能夠隨時(shí)修改。說(shuō)真的,如果我在文章中犯了拼寫(xiě)或者語(yǔ)法錯(cuò)誤,那么我需要能夠快速、頻繁的修改文章內(nèi)容。

模式二:可變的內(nèi)容,總是向服務(wù)器發(fā)起校驗(yàn)
Cache-Control: no-cache

同一個(gè)url對(duì)應(yīng)的內(nèi)容會(huì)改變

任何本地緩存的版本都是不可信的,除非服務(wù)器校驗(yàn)通過(guò)

注意:no-cache并不意味著不緩存,而是使用緩存前必須請(qǐng)求服務(wù)端進(jìn)行檢查(或者說(shuō)叫重新校驗(yàn))。no-store告訴瀏覽器,根本不要緩存這個(gè)文件。同時(shí),must-revalidate也不是說(shuō)就『must-revalidate』,而是如果本地資源的緩存時(shí)間還沒(méi)有超過(guò)設(shè)置的max-age的值,就可以直接使用本地資源,否則必須重新校驗(yàn)。

在這種模式下,你可以在響應(yīng)頭里添加一個(gè)ETag(你選擇的版本ID)或者Last-Modified。客戶端下一次請(qǐng)求資源時(shí),會(huì)分別帶上If-None-Match和If-Modified-Since,服務(wù)端會(huì)判斷說(shuō):直接使用你已有的本地資源吧,他們是最新的。這就是最常見(jiàn)的:HTTP 304

如果沒(méi)有帶上ETag/Last-Modified,服務(wù)端會(huì)再次返回完成的內(nèi)容。

這種模式總是會(huì)發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求,而模式一是可以不用通過(guò)網(wǎng)絡(luò)的。

使用模式一時(shí),因?yàn)榫W(wǎng)絡(luò)基礎(chǔ)建設(shè)而導(dǎo)致的延時(shí)是很常見(jiàn)的,使用模式二時(shí),也很容易遇到網(wǎng)絡(luò)環(huán)境帶來(lái)的延遲。取而代之的是中間的東西:一個(gè)短時(shí)間的max-age設(shè)置和可變的內(nèi)容。這是一種十分糟糕的妥協(xié)。

對(duì)可變內(nèi)容使用max-age通常是一個(gè)錯(cuò)誤的選擇

不幸的是,這種做法并非不常見(jiàn)。比如,Github pages就是這樣的。

想象一下有以下三個(gè)url:

/article/

/styles.css

/scripts.js

服務(wù)端都是返回的:

Cache-Control: must-revalidate, max-age=600

url對(duì)應(yīng)的內(nèi)容是變了

如果瀏覽器緩存了一個(gè)資源版本,但是沒(méi)有到10分鐘,會(huì)不經(jīng)過(guò)服務(wù)器直接使用這個(gè)緩存的資源。

否則發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求,帶上If-Modified-Since或者If-None-Match(如果可用)

這種模式在測(cè)試的時(shí)候看起來(lái)是可以的,但在現(xiàn)實(shí)中,會(huì)出問(wèn)題,并且很難追蹤。在上面的例子中,服務(wù)端確實(shí)已經(jīng)更新了HTML, CSS 和JS,但是頁(yè)面最終使用了緩存里的HTML,JS,CSS卻是從服務(wù)端獲取的最新的版本。資源版本不匹配導(dǎo)致了頁(yè)面出錯(cuò)。

通常情況下,當(dāng)我們對(duì)HTML進(jìn)行重大更改時(shí),我們還可能更改HTML對(duì)應(yīng)的CSS結(jié)構(gòu),并更新JS以適應(yīng)樣式和內(nèi)容的更改。這些資源是相互依賴的,但是緩存的header是無(wú)法描述這種依賴的。用戶最終看到的,可能是一兩個(gè)新版本的資源,和其他老的資源。

max-age和響應(yīng)時(shí)間有關(guān),因此,如果上述所有的資源都是在同一次訪問(wèn)中請(qǐng)求的,他們大概會(huì)在同一時(shí)間到期,但是仍然有很小的可能發(fā)生競(jìng)爭(zhēng)。如果你的某些頁(yè)面并不包含JS或者包含了不同的CSS,那么過(guò)期時(shí)間可能就不同步了。更糟糕的是,更糟糕的是,瀏覽器總是從緩存中刪除東西,它不知道HTML、CSS和JS是相互依賴的,所以它會(huì)很高興地刪除一個(gè)而不是其他的。上述的情況,都可能會(huì)導(dǎo)致頁(yè)面資源的版本不匹配。

對(duì)用戶來(lái)說(shuō),他們最終會(huì)看到錯(cuò)誤的頁(yè)面布局和錯(cuò)誤的頁(yè)面功能,從細(xì)微的錯(cuò)誤到完全不可用的內(nèi)容。

謝天謝地,對(duì)用戶來(lái)說(shuō)還是有補(bǔ)救措施的。

刷新可能會(huì)修復(fù)這個(gè)問(wèn)題

如果頁(yè)面作為刷新的一部分加載,瀏覽器會(huì)忽略max-age,向服務(wù)器進(jìn)行驗(yàn)證。因此,如果用戶遭遇了因?yàn)閙ax-age而造成的錯(cuò)誤,刷新是可以解決問(wèn)題的。當(dāng)然,強(qiáng)迫用戶這樣做會(huì)降低信任度,因?yàn)檫@會(huì)讓你感覺(jué)到你的網(wǎng)站是不靠譜的。

service worker可能會(huì)延長(zhǎng)這些bug的壽命

假設(shè)你有以下的service worker:

const version = "2";

self.addEventListener("install", event => {
  event.waitUntil(
    caches.open(`static-${version}`)
      .then(cache => cache.addAll([
        "/styles.css",
        "/script.js"
      ]))
  );
});

self.addEventListener("activate", event => {
  // …delete old caches…
});

self.addEventListener("fetch", event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  );
});

這個(gè)service-worker

緩存了script和style

如果命中了緩存,就從緩存中取,否則發(fā)起網(wǎng)絡(luò)請(qǐng)求

如果我們更改了CSS/JS,我們會(huì)修改service-worker中的版本號(hào),觸發(fā)service-worker的更新。但是,假如addAll發(fā)出的請(qǐng)求經(jīng)過(guò)了HTTP緩存(和其他大多數(shù)緩存一樣),我們也會(huì)進(jìn)入到max-age的race condition,緩存不匹配的CSS、JS版本。

一旦他們被緩存了,我們將會(huì)一直看到不匹配的CSS和JS,直到我們下一次更新service-worker。而在下一次更新時(shí),我們可能還會(huì)陷入另一個(gè)race condition。

你可以在service worker中跳過(guò)緩存:

self.addEventListener("install", event => {
  event.waitUntil(
    caches.open(`static-${version}`)
      .then(cache => cache.addAll([
        new Request("/styles.css", { cache: "no-cache" }),
        new Request("/script.js", { cache: "no-cache" })
      ]))
  );
});

不幸的是,這個(gè)緩存的設(shè)置在Chrome/Opera中還不支持,F(xiàn)irefox也是剛剛支持。你可以自己來(lái)實(shí)現(xiàn)類似的功能:

self.addEventListener("install", event => {
  event.waitUntil(
    caches.open(`static-${version}`)
      .then(cache => Promise.all(
        [
          "/styles.css",
          "/script.js"
        ].map(url => {
          // cache-bust using a random query string
          return fetch(`${url}?${Math.random()}`).then(response => {
            // fail on 404, 500 etc
            if (!response.ok) throw Error("Not ok");
            return cache.put(url, response);
          })
        })
      ))
  );
});

在上述代碼中,我用隨機(jī)數(shù)來(lái)避免緩存,但是你可以更進(jìn)一步,在構(gòu)建的時(shí)候?yàn)閮?nèi)容增加一個(gè)hash值(和sw-precache做的事差不多)。這是一種在js層面的對(duì)模式一的實(shí)現(xiàn),但是僅僅對(duì)service worker的使用者是有效的,而不是對(duì)所有的瀏覽器和你的CDN都有效。

service worker & http緩存可以同時(shí)使用,不要讓他們沖突

正如你所見(jiàn),你可以繞過(guò)service worker中糟糕的緩存,但是你最好解決根源的問(wèn)題。正確的設(shè)置緩存能夠讓你在使用service worker的時(shí)候更加輕松,并且對(duì)那些不支持service worker的瀏覽器也是有好處的,還能讓你充分的使用你的CDN。

正確的緩存頭還意味著你可以大量簡(jiǎn)化server worker的更新:

const version = "23";

self.addEventListener("install", event => {
  event.waitUntil(
    caches.open(`static-${version}`)
      .then(cache => cache.addAll([
        "/",
        "/script-f93bca2c.js",
        "/styles-a837cb1e.css",
        "/cats-0e9a2ef4.jpg"
      ]))
  );
});

在這里,我將使用模式2(服務(wù)器重新驗(yàn)證)緩存根頁(yè)面,其余資源使用模式1(不可變內(nèi)容)。每次service worker更新都將觸發(fā)對(duì)根頁(yè)面的請(qǐng)求,但只有當(dāng)資源的URL發(fā)生更改時(shí),才會(huì)下載其余資源。這很好,因?yàn)闊o(wú)論你是從以前的版本還是第10個(gè)版本更新,它都可以節(jié)省帶寬并提高性能。

相對(duì)于本地應(yīng)用來(lái)說(shuō),這是一個(gè)巨大的優(yōu)勢(shì)。在本地應(yīng)用中,不管二進(jìn)制內(nèi)容有細(xì)微和巨大的改變,整個(gè)二進(jìn)制內(nèi)容都會(huì)被下載。而在這里,我們只需要一個(gè)小小的下載,就能更新巨大的web app.

service worker的工作最好是作為一個(gè)增強(qiáng)方案,而不是變通方案。所以預(yù)期與緩存抗?fàn)?,不如好好利用緩存?/p> 謹(jǐn)慎使用,max-age & 可變內(nèi)容 也可以很有效

對(duì)于可變內(nèi)容使用max-age一般情況下是一個(gè)錯(cuò)誤的選擇,但也不總是這樣。比如,這個(gè)頁(yè)面設(shè)置了一個(gè)3分鐘的max-age. race condition在這個(gè)頁(yè)面是不會(huì)成為問(wèn)題的,因?yàn)檫@個(gè)頁(yè)面沒(méi)有任何遵循這一種模式的依賴(我的css,js,圖片等都遵循模式1-不可變內(nèi)容),依賴于此頁(yè)的任何內(nèi)容都不會(huì)遵循相同的模式。

這種模式意味著,如果我有幸寫(xiě)了一篇熱門文章,我的cdn可以讓我的服務(wù)器散熱,而我能忍受用戶需要花三分鐘時(shí)間才看到文章更新。

這種模式不能隨便使用。如果我在文章中添加了一個(gè)新的部分,并且將這個(gè)部分鏈接到一篇新的文章,那么我就創(chuàng)造了一個(gè)會(huì)爭(zhēng)用的依賴項(xiàng)。用戶可以單擊鏈接,并在沒(méi)有引用部分的情況下獲取文章的副本。如果我想避免這種情況,我就得更新第一篇文章,刷新cdn, 等待3分鐘,然后在另一篇文章中添加指向他的鏈接。是的…..你必須非常小心這種模式。

正確使用,緩存能極大的提高性能并且較少帶寬消耗。對(duì)于任何容易更改的URL,都支持不可變的內(nèi)容,否則在服務(wù)器重新驗(yàn)證時(shí)會(huì)使其安全。只有當(dāng)你足夠勇敢,并且你確信你沒(méi)有可能會(huì)失去同步的依賴項(xiàng)時(shí),再使用max-age和可變內(nèi)容的模式。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/62070.html

相關(guān)文章

  • 】-【緩存最佳實(shí)踐

    摘要:大部分服務(wù)器端的框架會(huì)有一些工具來(lái)讓這件事情變得簡(jiǎn)單,可是,這種方式并不適用于一些文章或者博客之類的網(wǎng)站,這些網(wǎng)站的不能通過(guò)版本號(hào)來(lái)管理,而且內(nèi)容也是經(jīng)常需要改變的。指不允許緩存。 本文譯自: 這里 本文已同步到我的博客 引言 緩存利用得當(dāng)?shù)脑?,有很大益處,比如?jié)省帶寬,降低服務(wù)器壓力等,但是很多網(wǎng)站沒(méi)能夠很好地利用緩存,造成一些相互依賴的資源出現(xiàn)不同步的情況。 關(guān)于緩存的處理方案主要...

    xavier 評(píng)論0 收藏0
  • 前端靜態(tài)資源緩存最優(yōu)解以及max-age陷阱

    摘要:前端靜態(tài)資源緩存最優(yōu)解以及的陷阱合理的使用緩存可以極大地提高網(wǎng)站的性能優(yōu)勢(shì),還可以節(jié)約帶寬從而降低服務(wù)器成本。此處注意和與第一天請(qǐng)求的版本號(hào)不同。既支持版本號(hào)類型的靜態(tài)資源緩存方式也支持服務(wù)器重新認(rèn)證的方式。 前端靜態(tài)資源緩存最優(yōu)解以及max-age的陷阱 合理的使用緩存可以極大地提高網(wǎng)站的性能優(yōu)勢(shì),還可以節(jié)約帶寬從而降低服務(wù)器成本。但是很多站點(diǎn)有只弄對(duì)了一半或者一半都沒(méi)有,如果是這樣...

    FrozenMap 評(píng)論0 收藏0
  • ELSE 技術(shù)周刊(2017.12.11期)

    摘要:業(yè)界動(dòng)態(tài)發(fā)布版本,同時(shí)發(fā)布了版本以及首個(gè)穩(wěn)定版本的。程序人生如何用人類的方式進(jìn)行二關(guān)于如何在中進(jìn)行良好的溝通,避免陷入一些潛在的陷阱。技術(shù)周刊由小組出品,匯聚一周好文章,周刊原文。 業(yè)界動(dòng)態(tài) Angular 5.1 & More Now Available Angular發(fā)布5.1版本,同時(shí)發(fā)布了Angular CLI 1.6版本以及首個(gè)穩(wěn)定版本的Angular Material。CL...

    tylin 評(píng)論0 收藏0
  • 】HTTP/2 Server Push 實(shí)踐:?jiǎn)?Link 報(bào)頭包含多資源場(chǎng)景

    摘要:記錄以下資源備忘也就是本文譯文標(biāo)題為意譯,原標(biāo)題為,恐有不當(dāng),特此說(shuō)明。譯者注翻譯本文時(shí)譯者使用的確實(shí)無(wú)法看到信息,建議使用最新金絲雀版本一探究竟。應(yīng)用程序不應(yīng)當(dāng)依賴于服務(wù)器推送的可用性及其使用。 本文轉(zhuǎn)載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/883原文:https://blog.cloudflare.com/http-2-server-pu...

    bbbbbb 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<