Základy cachování klientů srozumitelnými slovy a příklady. Last-modified, Etag, Expires, Cache-control: max-age a další hlavičky. Doporučené postupy ukládání do mezipaměti Jednoduché ukládání do mezipaměti ETag

Zahrnutím externích CSS a Javascriptu chceme omezit zbytečné HTTP požadavky na minimum.

Za tímto účelem jsou soubory .js a .css poskytovány s hlavičkami, které zajišťují spolehlivé ukládání do mezipaměti.

Co ale dělat, když se některý z těchto souborů během vývoje změní? Všichni uživatelé jej mají v mezipaměti stará verze- dokud nebude mezipaměť zastaralá, bude spousta stížností na nefunkční integraci serverové a klientské části.

Správné ukládání do mezipaměti a verzování tento problém zcela odstraňuje a poskytuje spolehlivou a transparentní synchronizaci verzí stylů/skriptů.

Jednoduché ukládání do mezipaměti ETag

Nejjednodušší způsob ukládání statických zdrojů do mezipaměti je použití ETag.

Stačí povolit příslušné nastavení serveru (pro Apache je standardně povoleno) - a pro každý soubor v záhlaví bude uveden ETag - hash, který závisí na době aktualizace, velikosti souboru a (na základě inodů souborové systémy) inode.

Prohlížeč uloží takový soubor do mezipaměti a při následných požadavcích určí hlavičku If-None-Match s ETag dokumentu uloženého v mezipaměti. Po přijetí takové hlavičky může server odpovědět kódem 304 - a poté bude dokument odebrán z mezipaměti.

Vypadá to takto:

První požadavek na server (vyčištění mezipaměti) GET /misc/pack.js HTTP/1.1 Host: web

Obecně platí, že prohlížeč obvykle přidává spoustu záhlaví, jako je User-Agent, Accept atd. Pro stručnost jsou střiženy.

Odezva serveru Server odpoví dokumentem s kódem 200 a ETag: HTTP/1.x 200 OK Kódování obsahu: gzip Typ obsahu: text/javascript; charset=utf-8 Etag: "3272221997" Accept-Ranges: bytes Content-Length: 23321 Date: Fri, 02 May 2008 17:22:46 GMT Server: lighttpd Další požadavek prohlížeče Při dalším požadavku prohlížeč přidá If-None -Match: (uložený ETag): GET /misc/pack.js HTTP/1.1 Host: site If-None-Match: "453700005" Odpověď serveru Server vypadá - ano, dokument se nezměnil. To znamená, že můžete vydat kód 304 a dokument neposílat znovu. HTTP/1.x 304 Neupraveno Kódování obsahu: gzip Etag: "453700005" Typ obsahu: text/javascript; charset=utf-8 Accept-Ranges: bytes Datum: Út, 15. dubna 2008 10:17:11 GMT

Alternativní možnost- pokud se dokument změnil, server jednoduše odešle 200 s novým ETag.

Kombinace Last-Modified + If-Modified-Since funguje podobným způsobem:

  • server odešle datum poslední úpravy v hlavičce Last-Modified (místo ETag)
  • prohlížeč uloží dokument do mezipaměti a při příštím požadavku na stejný dokument odešle datum verze uložené v mezipaměti v hlavičce If-Modified-Since (místo If-None-Match)
  • server zkontroluje data, a pokud se dokument nezměnil, odešle pouze kód 304 bez obsahu.
  • Tyto metody fungují spolehlivě a dobře, ale prohlížeč stejně musí udělat požadavek na každý skript nebo styl.

    Inteligentní ukládání do mezipaměti. Verzování

    Obecný přístup k verzování - v kostce:

  • Verze (nebo datum úpravy) je přidána do všech skriptů. Například http://site/my.js se změní na http://site/my.v1.2.js
  • Všechny skripty jsou pevně uloženy v mezipaměti prohlížeče
  • Při aktualizaci skriptu se verze změní na novou: http://site/my.v2.0.js
  • Adresa se změnila, takže prohlížeč si soubor znovu vyžádá a uloží do mezipaměti
  • Stará verze 1.2 bude postupně vypadávat z mezipaměti
  • Tvrdé ukládání do mezipaměti

    Tvrdé ukládání do mezipaměti- druh perlíku, který zcela přibije požadavky serveru na dokumenty uložené v mezipaměti.

    Chcete-li to provést, stačí přidat záhlaví Expires a Cache-Control: max-age.

    Chcete-li například ukládat do mezipaměti po dobu 365 dní v PHP:

    Header("Platnost vyprší: ".gmdate("D, d M Y H:i:s", time()+86400*365)." GMT"); header("Cache-Control: max-age="+86400*365);

    Nebo můžete obsah trvale uložit do mezipaměti pomocí mod_header v Apache:

    Po obdržení takových záhlaví prohlížeč ukládá dokument do mezipaměti po dlouhou dobu. Veškerý další přístup k dokumentu bude poskytován přímo z mezipaměti prohlížeče, bez kontaktování serveru.

    Většina prohlížečů (Opera, internet Explorer 6+, Safari) NEKACHUJTE dokumenty, pokud je v adrese otazník, protože jsou považovány za dynamické.

    Proto k názvu souboru přidáme verzi. Samozřejmě s takovými adresami musíte použít řešení jako mod_rewrite, na to se podíváme později v článku.

    P.S. Ale Firefox ukládá adresy s otazníky...

    Automatické rozlišení jmen

    Podívejme se na to, jak automaticky a transparentně měnit verze bez přejmenování samotných souborů.

    Název s verzí -> Soubor

    Nejjednodušší je převést název s verzí na původní název souboru.

    Na úrovni Apache to lze provést pomocí mod_rewrite:

    RewriteEngine na RewriteRule ^/(.*\.)v+\.(css|js|gif|png|jpg)$ /$1$2 [L]

    Toto pravidlo zpracuje všechny soubory css/js/gif/png/jpg a odstraní verzi z názvu.

    Například:

    /images/logo.v2.gif -> /images/logo.gif
    /css/style.v1.27.css -> /css/style.css
    /javascript/script.v6.js -> /javascript/script.js

    Ale kromě vyříznutí verze musíte do souborů přidat také hlavičky pro pevné mezipaměti. K tomu se používají direktivy mod_header:

    Přidat do záhlaví "Platnost vyprší" "Po, 28. července 2014 23:30:00 GMT" Přidat do záhlaví "Cache-Control" "max-age=315360000"

    A dohromady to implementuje následující konfiguraci Apache:

    RewriteEngine on # odstraní verzi a zároveň nastaví proměnnou, že soubor má verzi RewriteRule ^/(.*\.)v+\.(css|js|gif|png|jpg)$ /$1$2 # hard cache verzované soubory Přidat záhlaví "Platnost vyprší" "Po, 28 Jul 2014 23:30:00 GMT" env=VERSIONED_FILE Přidat záhlaví "Cache-Control" "max-age=315360000" env=VERSIONED_FILE

    Vzhledem k tomu, jak modul mod_rewrite funguje, musí být RewriteRule umístěno v hlavním konfigurační soubor httpd.conf nebo zahrnuté soubory, ale nikdy v .htaccess , jinak budou nejprve spuštěny příkazy Header před nastavením proměnné VERSIONED_FILE.

    Direktivy záhlaví mohou být kdekoli, dokonce i v .htaccess - na tom nezáleží.

    Automatické přidání verze k souboru na stránce HTML

    Jak vložit verzi do názvu skriptu závisí na vašem systému šablon a obecně na způsobu přidávání skriptů (stylů atd.).

    Například při použití data modifikace jako verze a nástroje Smarty šablon lze odkazy nastavit takto:

    Funkce verze přidá verzi:

    Function smarty_version($args)( $stat = stat($GLOBALS["config"]["site_root"].$args["src"]); $version = $stat["mtime"]; echo preg_replace("! \.(+?)$!", ".v$version.\$1", $args["src"]); )

    Výsledek na stránce:

    Optimalizace

    Abyste se vyhnuli zbytečným voláním statistik, můžete pole se seznamem aktuálních verzí uložit do samostatné proměnné

    $versions["css"] = array("group.css" => "1.1", "other.css" => "3.0", )

    V tomto případě se aktuální verze z pole jednoduše dosadí do HTML.

    Můžete zkřížit oba přístupy a během vývoje vytvořit verzi podle data modifikace - pro relevanci a ve výrobě - ​​verzi z pole, pro výkon.

    Použitelnost

    Tato metoda ukládání do mezipaměti funguje všude, včetně Javascriptu, CSS, obrázků, Flash filmů atd.

    Je to užitečné při každé změně dokumentu, ale prohlížeč by měl mít vždy aktuální, aktuální verzi.

    Cache hraje důležitou roli při provozu téměř každé webové aplikace na úrovni práce s databázemi, webovými servery a také na klientovi.

    V tomto článku se pokusíme porozumět ukládání klientů do mezipaměti. Zejména se podíváme na to, jaké HTTP hlavičky používají prohlížeče a webové servery a co znamenají.

    Nejprve si ale pojďme zjistit, proč je ukládání do mezipaměti na straně klienta vůbec potřeba? .

    Webové stránky se skládají z mnoha různé prvky: obrázky, soubory css a js atd. Některé z těchto prvků jsou použity na několika (mnoha) stránkách webu. Ukládání do mezipaměti na straně klienta označuje schopnost prohlížečů ukládat kopie souborů (odpovědi serveru), aby je nestahovaly znovu. To vám umožní výrazně urychlit opětovné načítání stránky, ušetřit provoz a také snížit zatížení serveru.

    Existuje několik různých hlaviček HTTP pro řízení procesů ukládání do mezipaměti na straně klienta. Promluvme si o každém z nich.

    Http hlavičky pro řízení klientské mezipaměti

    Nejprve se podíváme na to, jak server a prohlížeč spolupracují při absenci jakéhokoli ukládání do mezipaměti. Pro jasné pochopení jsem se pokusil představit a vizualizovat proces komunikace mezi nimi formou textového chatu. Představte si na pár minut, že server a prohlížeč jsou lidé, kteří si vzájemně dopisují :)

    Bez mezipaměti (při absenci mezipaměti hlaviček http)

    Jak vidíme, pokaždé, když se zobrazí obrázek cat.png, prohlížeč jej znovu stáhne ze serveru. Myslím, že není třeba vysvětlovat, že je to pomalé a neúčinné.

    Hlavička poslední změny odpovědi a hlavička požadavku if-Modified-Since.

    Myšlenka je taková, že server přidá do souboru (odpovědi), který dává prohlížeči, hlavičku Last-modified.

    Prohlížeč nyní ví, že soubor byl vytvořen (nebo upraven) 1. prosince 2014. Až bude prohlížeč příště potřebovat stejný soubor, odešle požadavek s hlavičkou if-Modified-Since.

    Pokud soubor nebyl změněn, server odešle do prohlížeče prázdnou odpověď se stavem 304 (nezměněno). V tomto případě prohlížeč ví, že soubor nebyl aktualizován, a může zobrazit kopii, kterou naposledy uložil.

    Pomocí Last-modified tedy ušetříme na načítání velký soubor, vystoupí s prázdnou rychlou odpovědí ze serveru.

    Záhlaví odpovědi Etag a záhlaví požadavku If-None-Match.

    Princip fungování Etagu je velmi podobný Last-modified, ale na rozdíl od něj není vázán na čas. Čas je relativní věc.

    Myšlenka je taková, že když je vytvořen a pokaždé, když se změní, server označí soubor speciální značkou nazvanou ETag a také přidá hlavičku do souboru (odpověď), kterou odešle do prohlížeče:

    ETAG: "686897696a7c876b7e"

    Nyní prohlížeč ví, že soubor aktuální verze má ETag rovný „686897696a7c876b7e“. Až bude prohlížeč příště potřebovat stejný soubor, odešle požadavek s hlavičkou If-None-Match: "686897696a7c876b7e" .

    If-None-Match: "686897696a7c876b7e"

    Server může porovnat štítky a pokud soubor nebyl změněn, odeslat do prohlížeče prázdnou odpověď se stavem 304 (nezměněno). Stejně jako u Last-modified prohlížeč zjistí, že soubor nebyl aktualizován a bude moci zobrazit kopii z mezipaměti.

    Platnost titulu vypršela

    Princip fungování této hlavičky se liší od výše popsaných Etag a Last-modified. Pomocí Expired se určí „datum vypršení platnosti“ („doba relevance“) souboru. Tito. Při prvním načtení server oznámí prohlížeči, že neplánuje změnit soubor do data uvedeného v části Expired:

    Příště se prohlížeč s vědomím, že „datum vypršení platnosti“ ještě nenaplnil, ani nepokusí odeslat požadavek na server a zobrazí soubor z mezipaměti.

    Tento typ mezipaměti je zvláště důležitý pro ilustrace článků, ikon, favicon, některých souborů css a js atd.

    Hlavička řízení mezipaměti s direktivou max-age.

    Princip fungování Cache-control: max-age je velmi podobný Expired. Zde se také určuje „datum expirace“ souboru, ale nastavuje se v sekundách a není vázáno na konkrétní čas, což je ve většině případů mnohem pohodlnější.

    Pro referenci:

    • 1 den = 86 400 sekund
    • 1 týden = 604 800 sekund
    • 1 měsíc = 2629000 sekund
    • 1 rok = 31536000 sekund

    Např:

    Cache-Control: max-age=2629000;

    Hlavička Cache-control má kromě max-age další direktivy. Pojďme se rychle podívat na ty nejoblíbenější:

    veřejnost
    Faktem je, že požadavky může ukládat do mezipaměti nejen koncový klient uživatele (prohlížeč), ale také různé zprostředkující proxy, sítě CDN atd. Direktiva public tedy umožňuje absolutně libovolnému proxy serveru provádět ukládání do mezipaměti stejně jako prohlížeč.

    soukromé
    Směrnice to uvádí tento soubor(odpověď serveru) je specifická pro koncového uživatele a neměla by být ukládána do mezipaměti různými zprostředkujícími proxy. Zároveň umožňuje ukládání do mezipaměti koncovému klientovi (prohlížeči uživatele). To je například relevantní pro stránky interního uživatelského profilu, požadavky v rámci relace atd.

    Umožňuje určit, že klient by měl vždy zadat požadavek na server. Někdy se používá s výše popsanou hlavičkou Etag.

    no-store
    Dává klientovi pokyn, že by si za žádných okolností neměl uchovávat kopii žádosti nebo její části. Toto je nejpřísnější hlavička, která přepíše všechny mezipaměti. Byl vynalezen speciálně pro práci s důvěrnými informacemi.

    musí znovu ověřit
    Tato direktiva dává prohlížeči pokyn, aby provedl povinný požadavek na server, aby znovu ověřil obsah (například pokud používáte eTag). Faktem je, že http v určité konfiguraci umožňuje mezipaměť ukládat obsah, který je již zastaralý. must-revalidate zavazuje prohlížeč, aby za jakýchkoli okolností zkontroloval čerstvost obsahu odesláním požadavku na server.

    proxy-revalidate
    To je stejné jako nutnost znovu ověřit, ale vztahuje se pouze na servery proxy pro ukládání do mezipaměti.

    s-maxage
    Prakticky se neliší od max-age , kromě toho, že tuto direktivu bere v úvahu pouze mezipaměť různých proxy, ale ne samotný prohlížeč uživatele. Písmeno „s -“ pochází ze slova „shared“ (např. CDN). Tato směrnice je určena speciálně pro sítě CDN a další zprostředkující mezipaměti. Jeho zadáním se přepíší hodnoty direktivy max-age a hlavičky Expired. Pokud však nevytváříte sítě CDN, je nepravděpodobné, že byste s-maxage někdy potřebovali.

    Jak zjistím, jaká záhlaví se na webu používají?

    Záhlaví požadavku http a záhlaví odpovědí můžete zobrazit v ladicím programu svého oblíbeného prohlížeče. Zde je příklad toho, jak to vypadá v Chrome:

    Totéž lze vidět v každém seberespektujícím prohlížeči nebo http snifferu.

    Nastavení ukládání do mezipaměti v Apache a Nginx

    Nebudeme převyprávět dokumentaci pro nastavení oblíbených serverů. Vždy se na to můžete dívat a. Níže uvedeme několik příkladů ze skutečného života, abychom ukázali, jak vypadají konfigurační soubory.

    Příklad Konfigurace Apache ovládat Expires

    Nastavili jsme různá „data vypršení platnosti“. různé typy soubory. Jeden rok pro obrázky, jeden měsíc pro skripty, styly, soubory PDF a ikony. Na vše ostatní – 2 dny.

    ExpiresActive On ExpiresByType image/jpg "přístup plus 1 rok" ExpiresByType image/jpeg "přístup plus 1 rok" ExpiresByType image/gif "přístup plus 1 rok" ExpiresByType image/png "přístup plus 1 rok" ExpiresByType plus text/cssType plus text/cs měsíc" ExpiresByType application/pdf "přístup plus 1 měsíc" ExpiresByType text/x-javascript "přístup plus 1 měsíc" ExpiresByType image/x-icon "přístup plus 1 rok" ExpiresDefault "přístup plus 2 dny"

    Příklad konfigurace Nginx pro ovládání Expires

    Pro různé typy souborů jsme nastavili různá „data vypršení platnosti“. Jeden týden na obrázky, jeden den na styly a skripty.

    Server ( #... umístění ~* \.(gif|ico|jpe?g|png)(\?+)?$ (platnost vyprší 1 týden; ) umístění ~* \.(css|js)$ (platnost vyprší 1 d; ) #...)

    Příklad konfigurace Apache pro Cache-control (max-age a public/private/no-cache) Header set Cache-Control "max-age=2592000, public" Header set Cache-Control "max-age=88000, private, must- revalidate" Sada hlaviček Cache-Control "private, no-store, no-cache, must-revalidate, no-transform, max-age=0" Header set Pragma "no-cache" Příklad konfigurace Nginx pro server se statickými soubory řízení mezipaměti ( #... umístění ~* \.(?:ico|css|js|gif|jpe?g|png)$ ( add_header Cache-Control "max-age=88000, public"; ) #... ) V závěr

    „Ukládat do mezipaměti vše, co lze uložit do mezipaměti“ je dobré motto pro vývojáře webu. Někdy můžete strávit jen pár hodin nad konfigurací a zároveň výrazně zlepšit uživatelský zážitek z vašeho webu, výrazně snížit zatížení serveru a ušetřit na provozu. Hlavní věcí není přehánět a správně nastavit vše s přihlédnutím k vlastnostem vašeho zdroje.

    Správně nakonfigurované ukládání do mezipaměti poskytuje obrovské výhody v oblasti výkonu, šetří šířku pásma a snižuje náklady na server, ale mnoho webů implementuje ukládání do mezipaměti špatně, což způsobuje konflikt, který způsobuje, že se vzájemně propojené zdroje nesynchronizují.

    Drtivá většina osvědčené postupy ukládání do mezipaměti se týká jednoho ze dvou vzorů:

    Vzor č. 1: neměnný obsah a dlouhá maximální věková mezipaměť Cache-Control: max-age=31536000
    • Obsah URL se nemění, proto...
    • Prohlížeč nebo CDN může zdroj snadno ukládat do mezipaměti po dobu jednoho roku
    • Obsah mezipaměti, který je mladší než zadaný maximální věk, lze použít bez konzultace se serverem

    Stránka: Ahoj, potřebuji "/script-v1.js" , "/styles-v1.css" a "/cats-v1.jpg" 10:24

    Cash: Jsem prázdný, co vy, server? 10:24

    Server: Dobře, tady jsou. Mimochodem, hotovost, měly by se používat rok, ne déle. 10:25

    Cash: Děkuji! 10:25

    Strana: Hurá! 10:25

    Další den

    Stránka: Ahoj, potřebuji "/script-v2 .js" , "/styles-v2 .css" a "/cats-v1.jpg" 08:14

    Cash: Je tam obrázek s kočkami, ale ne zbytek. server? 08:14

    Server: Snadno – zde je nový CSS & JS. Ještě jednou Cash: jejich trvanlivost není delší než rok. 08:15

    Cash: Skvělé! 08:15

    Stránka: Děkuji! 08:15

    Cash: Hmm, už nějakou dobu jsem nepoužil "/script-v1.js" & "/styles-v1.css". Je čas je odstranit. 12:32

    Pomocí tohoto vzoru nikdy nezměníte obsah konkrétní adresy URL, změníte samotnou adresu URL:

    Každá adresa URL má něco, co se mění spolu s obsahem. Může to být číslo verze, upravené datum nebo hash obsahu (což jsem zvolil pro svůj blog).

    Většina serverových frameworků má nástroje, které vám umožňují dělat takové věci snadno (v Django používám Manifest​Static​Files​Storage); V Node.js jsou také velmi malé knihovny, které řeší stejné problémy, například gulp-rev.

    Tento vzor však není vhodný pro věci, jako jsou články a blogové příspěvky. Jejich adresy URL nelze upravovat a jejich obsah se může změnit. Vážně, často mám gramatické a interpunkční chyby a potřebuji rychle aktualizovat obsah.

    Vzor č. 2: měnitelný obsah, který je vždy ověřen na serveru Cache-Control: no-cache
    • Obsah adresy URL se změní, což znamená...
    • Žádnou lokálně uloženou verzi nelze použít bez určení serveru.

    Stránka: Ahoj, potřebuji obsah "/about/" a "/sw.js" 11:32

    Cash: Nemůžu ti pomoct. server? 11:32

    Server: Jsou nějaké. Hotovost, mějte je u sebe, ale než je použijete, zeptejte se mě. 11:33

    Cash: Přesně! 11:33

    Stránka: Děkuji! 11:33

    Další den

    Stránka: Ahoj, potřebuji znovu obsah "/about/" a "/sw.js" 09:46

    Cash: Ještě chvilku. Server, jsou moje kopie v pořádku? Kopie „/about/“ je z pondělí a „/sw.js“ je ze včerejška. 09:46

    Server: "/sw.js" se nezměnil... 09:47

    Hotovost: V pohodě. Stránka, ponechte "/sw.js" . 09:47

    Server: …ale mám „/about/“ nová verze. Hotovost, drž to, ale jako minule se mě nejdřív nezapomeň zeptat. 09:47

    Cash: Rozumím! 09:47

    Strana: Skvělé! 09:47

    Poznámka: no-cache neznamená „neukládat do mezipaměti“, znamená to „zkontrolovat“ (nebo znovu ověřit) prostředek uložený v mezipaměti na serveru. A no-store říká prohlížeči, aby se do mezipaměti vůbec nepouštěl. Také must-revalidate neznamená povinné opětovné ověření, ale to, že prostředek uložený v mezipaměti se použije pouze v případě, že je mladší než zadaný max-age , a pouze jinak se znovu ověří. Takhle to všechno začalo klíčová slova pro ukládání do mezipaměti.

    V tomto vzoru můžeme k odpovědi přidat ETag (ID verze dle vašeho výběru) nebo hlavičku Last-Modified. Až si klient příště vyžádá obsah, vypíše se If-None-Match nebo If-Modified-Since, což serveru umožní říct „Používejte, co máte, vaše mezipaměť je aktuální“, tj. vrátí HTTP 304.

    Pokud odeslání ETag / Last-Modified není možné, server vždy odešle celý obsah.

    Tento vzor vždy vyžaduje síťová volání, takže není tak dobrý jako první vzor, ​​který se obejde bez síťových požadavků.

    Není neobvyklé, že nemáme infrastrukturu pro první vzor, ​​ale mohou nastat i problémy se síťovými požadavky ve vzoru 2. V důsledku toho se používá mezilehlá možnost: krátký maximální věk a proměnlivý obsah. To je špatný kompromis.

    Použití max-age s proměnlivým obsahem je obecně špatná volba

    A bohužel je to běžné; příkladem jsou stránky Github.

    Představ si:

    • /článek/
    • /styles.css
    • /script.js

    S hlavičkou serveru:

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

    • Obsah URL se změní
    • Pokud má prohlížeč verzi uloženou v mezipaměti novější než 10 minut, použije se bez konzultace se serverem
    • Pokud taková mezipaměť neexistuje, použije se síťový požadavek, pokud možno s If-Modified-Since nebo If-None-Match

    Stránka: Ahoj, potřebuji "/article/", "/script.js" a "/styles.css" 10:21

    Cash: Nemám nic, jako ty, server? 10:21

    Server: Žádný problém, tady jsou. Ale pamatujte, hotovost: mohou být použity během následujících 10 minut. 10:22

    Hotovost: Ano! 10:22

    Stránka: Děkuji! 10:22

    Stránka: Ahoj, potřebuji znovu "/article/", "/script.js" a "/styles.css" 10:28

    Cash: Jejda, omlouvám se, ale ztratil jsem „/styles.css“, ale všechno ostatní mám, tady to máš. Server, můžete mi přizpůsobit "/styles.css"? 10:28

    Server: Klid, už se změnil od doby, kdy jsi ho naposledy vzal. Následujících 10 minut jej můžete bezpečně používat. 10:29

    Hotovost: Žádný problém. 10:29

    Stránka: Děkuji! Ale zdá se, že se něco pokazilo! Všechno je rozbité! Co se děje? 10:29

    Tento vzor má právo na život během testování, ale ve skutečném projektu rozbije vše a je velmi obtížné jej sledovat. Ve výše uvedeném příkladu server aktualizoval HTML, CSS a JS, ale stránka se vykresluje pomocí starého kódu HTML a JS uloženého v mezipaměti plus aktualizovaného CSS ze serveru. Nesoulad verzí všechno zničí.

    Když provádíme významné změny v HTML, často měníme jak CSS, aby správně odrážely novou strukturu, tak JavaScript, abychom udrželi krok s obsahem a styly. Všechny tyto prostředky jsou nezávislé, ale hlavičky mezipaměti to nemohou vyjádřit. V důsledku toho mohou uživatelé najít sami sebe Nejnovější verze jeden/dva zdroje a stará verze zbytku.

    max-age je nastaven relativně k době odezvy, takže pokud jsou všechny zdroje přeneseny jako součást jedné adresy, jejich platnost vyprší ve stejnou dobu, ale stále existuje malá šance na desynchronizaci. Pokud máte stránky, které neobsahují JavaScript nebo obsahují jiné styly, data vypršení jejich mezipaměti nebudou synchronizována. A co je horší, prohlížeč neustále vytahuje obsah z mezipaměti, aniž by věděl, že HTML, CSS a JS jsou vzájemně závislé, takže může vesele vytáhnout jednu věc ze seznamu a zapomenout na všechno ostatní. Když vezmete v úvahu všechny tyto faktory dohromady, měli byste pochopit, že pravděpodobnost neshodných verzí je poměrně vysoká.

    Pro uživatele může být výsledkem nefunkční rozvržení stránky nebo jiné problémy. Od drobných závad až po zcela nepoužitelný obsah.

    Naštěstí mají uživatelé nouzový východ...

    Někdy pomůže obnovení stránky

    Pokud se stránka načte obnovením, prohlížeče vždy provedou revalidaci na straně serveru a ignorují max-age . Pokud má tedy uživatel něco rozbité kvůli max-age , může jednoduché obnovení stránky vše napravit. Ale samozřejmě po nalezení lžiček zůstane sediment a postoj k vašemu webu bude poněkud odlišný.

    Servisní pracovník může životnost těchto chyb prodloužit

    Máte například servisního pracovníka, jako je tento:

    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 => ( // ...smazat staré cache... )); self.addEventListener("fetch", event => ( event.respondWith(caches.match(event.request) .then(response => response || fetch(event.request))); ));

    Tento servisní pracovník:

    • ukládá skript a styly do mezipaměti
    • používá mezipaměť, pokud existuje shoda, jinak přistupuje k síti

    Pokud změníme CSS/JS, zvýšíme také číslo verze, což spustí aktualizaci. Protože však addAll přistupuje k mezipaměti jako první, můžeme se dostat do konfliktního stavu kvůli maximálnímu věku a neshodám s verzemi CSS a JS.

    Jakmile budou uloženy do mezipaměti, budeme mít nekompatibilní CSS a JS až do příští aktualizace servisního pracovníka – a to pokud se během aktualizace znovu nedostaneme do konfliktu.

    Ukládání do mezipaměti můžete přeskočit v servisním pracovníkovi:

    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" )) ]))); ));

    Možnosti ukládání do mezipaměti bohužel nejsou v prohlížeči Chrome/Opera podporovány a byly právě přidány do nočního sestavení Firefoxu, ale můžete to udělat sami:

    Self.addEventListener("install", event => ( event.waitUntil(caches.open(`static-$(version)`) .then(cache => Promise.all([ "/styles.css", "/script .js" ].map(url => ( // výpadek mezipaměti pomocí náhodného řetězce dotazu return fetch(`$(url)?$(Math.random())`).then(response => ( // neúspěšné na 404, 500 atd. if (!response.ok) throw Error("Not ok"); return cache.put(url, response); )) ))))); ));

    V tomto příkladu resetuji mezipaměť pomocí náhodného čísla, ale můžete jít dále a přidat hash obsahu při vytváření (toto je podobné tomu, co dělá sw-precache). Toto je druh implementace prvního vzoru pomocí JavaScriptu, ale funguje pouze se servisním pracovníkem, nikoli s prohlížeči a CDN.

    Servisní pracovníci a HTTP cache skvěle spolupracují, nenuťte je bojovat!

    Jak vidíte, chyby ukládání do mezipaměti můžete obejít ve svém servisním pracovníkovi, ale je lepší vyřešit kořen problému. Správné nastavení ukládání do mezipaměti nejen usnadňuje práci servisního pracovníka, ale také pomáhá prohlížečům, které nepodporují servisní pracovníky (Safari, IE/Edge), a také vám umožňuje vytěžit maximum z vašeho CDN.

    Správné hlavičky mezipaměti mohou také výrazně usnadnit aktualizaci servisního pracovníka.

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

    Zde jsem uložil kořenovou stránku se vzorem #2 (revalidace na straně serveru) a všechny ostatní zdroje se vzorem #1 (neměnný obsah). Každá aktualizace servisního pracovníka způsobí požadavek na kořenovou stránku a všechny ostatní zdroje budou načteny pouze v případě, že se změnila jejich adresa URL. To je dobré, protože to šetří provoz a zlepšuje výkon, bez ohledu na to, zda upgradujete z předchozího nebo velmi stará verze.

    Zde je značná výhoda oproti nativní implementaci, kdy se i při malé změně stáhne celá binárka nebo způsobí složité srovnání binární soubory. Můžeme tak aktualizovat velkou webovou aplikaci s relativně malým zatížením.

    Servisní pracovníci fungují lépe jako vylepšení než dočasná berlička, takže místo boje s vyrovnávací pamětí pracujte.

    Při pečlivém použití může být maximální věk a variabilní obsah velmi dobrý

    max-age je velmi často špatnou volbou pro měnitelný obsah, ale ne vždy. Například původní článek má maximální stáří tři minuty. Spor není problém, protože na stránce nejsou žádné závislosti používající stejný vzor ukládání do mezipaměti (CSS, JS a obrázky používají vzor #1 - neměnný obsah), vše ostatní tento vzor nepoužívá.

    Tento vzorec znamená, že mohu pohodlně psát oblíbený článek a moje CDN (Cloudflare) může ubrat zátěži serveru, pokud jsem ochoten počkat tři minuty, než bude aktualizovaný článek dostupný. přístupné uživatelům.

    Tento vzor by měl být používán bez fanatismu. Pokud jsem do článku přidal novou sekci a odkazoval na ni z jiného článku, vytvořil jsem závislost, kterou je třeba vyřešit. Uživatel může kliknout na odkaz a získat kopii článku bez požadované sekce. Pokud se tomu chci vyhnout, měl bych článek obnovit, smazat verzi článku uloženou v mezipaměti z Cloudflare, počkat tři minuty a teprve poté přidat odkaz na jiný článek. Ano, tento vzorec vyžaduje opatrnost.

    Při správném použití poskytuje ukládání do mezipaměti výrazné zlepšení výkonu a úsporu šířky pásma. Poskytujte neměnný obsah, pokud můžete snadno změnit adresu URL, nebo použijte opětovné ověření na straně serveru. Pokud jste dostatečně odvážní a jste si jisti, že váš obsah nemá závislosti, které by se mohly vymknout synchronizaci, smíchejte maximální věk a měnitelný obsah.

    Při změnách na webových stránkách se často setkáváme s tím, že obsah stránek, css souborů a skriptů (.js) prohlížeč ukládá do mezipaměti a zůstává poměrně dlouho nezměněn. To vede k tomu, že aby se provedené změny projevily ve všech prohlížečích, je nutné klienty navyknout na složité kombinace F5 nebo Ctrl + F5. A čas od času se ujistěte, že jsou stisknuté.

    Proces je poměrně zdlouhavý a nepohodlný. Ze situace se samozřejmě můžete dostat tak, že soubory pokaždé přejmenujete, ale opět je to nepohodlné.

    Existuje však způsob, který nám umožní zůstat se stejnými názvy a resetovat ukládání souborů .css nebo .js do mezipaměti v okamžiku, kdy to potřebujeme. A navždy zapomeňte na Ctrl + F5.

    Základem je, že k našim .css nebo .js souborům na konci připojíme pseudoparametr, který budeme čas od času měnit, čímž resetujeme cache v prohlížeči.

    Tedy vstup do zdrojový kód bude nyní vypadat takto:

    Kde 186485 je libovolná kombinace, která vygeneruje stejný soubor, ale prohlížeč jej interpretuje jako nový, díky pseudoparametru ?186485

    Nyní, abychom pokaždé neměnili všechny výskyty našeho parametru, nastavíme jej do php souboru, který propojíme se všemi místy, která potřebujeme: