Stilovi predmemoriranja. Najbolje prakse predmemoriranja. Kako radi Cache-Control?

HTML5 omogućuje izradu web aplikacija koje će raditi čak i bez internetske veze.

Poboljšano predmemoriranje stranica

Napomena: IE10+, Chrome, Firefox, Opera i Safari podržavaju ovu tehnologiju.

HTML5 poboljšava mogućnosti predmemoriranja preglednika. Web stranice sada mogu biti u potpunosti dostupne korisnicima čak i bez internetske veze.

Korištenje HTML5 predmemoriranja pruža sljedeće prednosti:

  • Korisnicima omogućuje pregled web stranica čak i bez internetske veze.
  • Povećana brzina učitavanja stranica - stranice se pohranjuju lokalno na računalu korisnika i stoga će se učitavati mnogo brže.
  • Smanjeno opterećenje poslužitelja - poslužitelj neće morati obrađivati ​​neke od korisničkih zahtjeva.
Primjer korištenja HTML5 predmemoriranja

...Sadržaj dokumenta...

Deklariranje HTML5 predmemoriranja

Kako biste koristili mehanizam predmemoriranja na svojim web stranicama, morate oznaci dodati atribut manifest i kao njegovu vrijednost navesti put do posebne datoteke u kojoj su deklarirani parametri predmemoriranja.

Ako ovaj atribut nije postavljen na web-stranici i veza na njega nije u datoteci predmemorije, stranica neće biti spremljena u predmemoriju.

Datoteka predmemorije može imati bilo koju ekstenziju (na primjer.appcache ili.mf), ali mora imati poseban MIME tip: "text/cache-manifest".

U nekim slučajevima web-poslužitelj može trebati dodatnu konfiguraciju za posluživanje određene MIME vrste. Na primjer, za konfiguraciju Apache web poslužitelja trebate dodati sljedeći kod u .htaccess datoteku:

AddType text/cache-manifest .appcache

Sadržaj datoteke predmemorije

Datoteka predmemorije obična je tekstualna datoteka koja govori pregledniku koje datoteke treba spremiti u predmemoriju.

Datoteka može sadržavati tri odjeljka:

  • CACHE MANIFEST - ovaj odjeljak specificira veze na datoteke koje je potrebno predmemorirati. Preglednik će automatski spremiti u predmemoriju sve navedene datoteke odmah nakon prvog preuzimanja.
  • MREŽA - ovaj odjeljak navodi datoteke koje zahtijevaju stalnu internetsku vezu. Preglednik neće spremati datoteke navedene u ovom odjeljku.
  • ZAMJENA - ako su datoteke navedene u ovom odjeljku nedostupne iz bilo kojeg razloga, korisnici će biti automatski preusmjereni na drugu navedenu datoteku.

Odjeljak CACHE MANIFEST mora biti prisutan u svim datotekama predmemorije. Možda nedostaju odjeljci NETWORK i FALLBACK.

Primjer datoteke predmemorije:

CACHE MANIFEST #Ovaj odjeljak navodi datoteke koje će biti pohranjene u predmemoriju index.html flower.png MREŽA #Ovaj odjeljak navodi datoteke koje zahtijevaju internetsku vezu login-page.php FALLBACK #Ako mob.html nije dostupan, korisnik će biti preusmjeren na offline.html /mob .html /offline.html #Ako bilo koja od HTML datoteka nije dostupna, korisnik će biti preusmjeren na offline.html *.html /offline.html

Imajte na umu: web stranica koja povezuje na datoteku predmemorije bit će automatski pohranjena u predmemoriju, tako da je uključivanje u samu datoteku predmemorije opcionalno, ali se ipak preporučuje.

Imajte na umu: neki preglednici mogu imati ograničenje veličine predmemoriranog sadržaja na jednoj stranici.

Ažuriranje predmemoriranih datoteka

Nakon što se datoteke pohrane u predmemoriju, preglednik će nastaviti prikazivati ​​njihovu predmemoriranu verziju uvijek iznova čak i ako promijenite sadržaj tih datoteka na poslužitelju.

Za ažuriranje predmemoriranog sadržaja morate učiniti nešto od sljedećeg:

  • Očistite predmemoriju u pregledniku korisnika
  • Ažurirajte sadržaj datoteke predmemorije
  • Programski osvježi predmemoriju preglednika (koristeći JavaScript)

Kako biste ažurirali sadržaj datoteke, možete upotrijebiti sljedeći trik: umjesto izravnog ažuriranja sadržaja datoteke, možete joj dodati komentar navodeći datum izmjene i/ili verziju datoteke i u ubuduće promijenite samo sadržaj ovog komentara kad god želite osvježiti sadržaj u predmemoriji.

Mnogi ljudi misle da prema zadanim postavkama CSS datoteke povezane putem veze ili @import nisu predmemorirane. Moram te razočarati. To je css koji se nalazi u zasebnoj datoteci koja je predmemorirana, i to vrlo dobro, rekao bih izvrsno. Ove informacije su pouzdano provjerene na 6 i novijim i drugim preglednicima. Vrijedno je napomenuti da mnogi ljudi predmemoriraju takve datoteke divljom brzinom, da tako kažem, zauzimaju prvo mjesto po ovom pitanju. Usput, u mnogim slučajevima upravo ovaj mehanizam Opera ima značajnu brzinu u usporedbi s drugim preglednicima. Ali odmah ću reći da upravo ovo "super" predmemoriranje u Operi igra okrutnu šalu s njim kada se koristi AJAX tehnologija. Dok drugi rade puno promjena kada koriste AJAX, Opera preuzima stari. Ali ovo je pjesma o posebnoj temi.

CSS predmemoriranje

ALI! Ipak, neki ljudi imaju problema u tom smjeru. To je obično zbog neispravno konfiguriranog Apache poslužitelja, koji proizvodi ne sasvim ispravna zaglavlja. Pomoću zaglavlja možete kontrolirati predmemoriju datoteka. Prema zadanim postavkama, naravno, predmemorija je uvijek omogućena. Ali ponekad nema potrebe za spremanjem datoteka u predmemoriju. Iz tog razloga, čak i profesionalci počinju plesati s tamburama u vezi HTTP zaglavlja. Ali ako ste pročitali ovaj cijeli članak, onda ste još daleko od upravljanja HTTP zaglavljima. Uvjeravam vas da se u bliskoj budućnosti nećete suočiti s takvim problemom. Pa ipak, ako ste znatiželjni do srži, onda ću vam ukratko reći kako se to događa.

  • šalje HTTP zaglavlje WEB poslužitelju - kažu slušaj, slatka paprika, daj mi CSS datoteku, inače imam CSS, ali u zadnje vrijeme ima ovakvih promjena.
  • A poslužitelj mu odgovara, dušo, nije bilo promjena od tog trenutka, slobodno uzmi i koristi svoj stari CSS.
  • Ako se CSS promijenio, tada preglednik glupo ažurira CSS u svojoj predmemoriji.
  • E, sad, ako nisam umoran, onda malo znanstvenog smeća od nekakvog eksperimenta.

    Odmah ću reći da će početnici na WEB-u slabo razumjeti donji tekst. Ovo će uglavnom biti korisno onima koji se suočavaju sa zadatkom onemogućavanja i omogućavanja predmemorije.

    Svi eksperimenti provedeni su na stvarnom, plaćenom. Dobar hoster, da tako kažem, koji vam omogućuje promjenu strukture HTTP zaglavlja bez paranoje da će biti hakiran na temelju HTTP zaglavlja :)

    Načini rada preglednika

    Dakle, svaki preglednik ima 2 načina rada:

    1. Zadani način rada, povratno zaglavlje:

    Kontrola predmemorije: bez pohrane, bez predmemorije, mora se ponovo potvrditi, naknadna provjera=0, prethodna provjera=0

    2. Način rada s omogućenim predmemoriranjem, vraćeno zaglavlje:

    Kontrola predmemorije: privatno, max-age=10800, prethodna provjera=10800

    Zatim opisujem ponašanje preglednika FireFox 3.5 i novijih

    U prvom načinu rada čvrsto sprema vanjske JavaScript datoteke i čak ne provjerava njihova ažuriranja, osim ako je stranica prisiljena osvježiti se. CSS se provjerava zahtjevom zaglavlja.

    If-Modified-Since: "trenutni datum" GMT If-None-Match: "prilagođeni hash kod"

    To jest, CSS se ponovno učitava samo ako je stvarno ažuriran.

    Drugo, drugi način prestaje ažurirati stranicu u potpunosti. Odnosno, čak i ako smo promijenili sadržaj prikazan na stranici u bazi podataka, ona to ne prikazuje, čak i ako je prisilno ažuriramo, jer šalje zahtjev:

    GET / HTTP/1.1 Host: xxx.com If-Modified-Since: trenutni datum GMT

    i dobije odgovor:

    HTTP/1.1 304 Nije izmijenjeno

    Internet Explorer 8 (IE8)

    U prvom načinu, Internet Explorer šalje zahtjeve If-Modified-Since & If-None-Match i za JavaScript i za CSS, odnosno učitava JavaScript i CSS samo ako su stvarno ažurirani. Ista stvar se događa ako prisilno osvježite stranicu.

    U drugom načinu, Internet Explorer također šalje zahtjeve If-Modified-Since & If-None-Match i za JavaScript i za css. Ali pritom niti ne pokušava učitati/ažurirati samu stranicu, odnosno niti ne šalje zahtjev, odnosno vaš js/css će se ažurirati, ali predložak i sadržaj stranice neće. Čak ni prisilno osvježavanje stranice ne pomaže u ažuriranju sadržaja.

    Opera 10 i starije

    U prvom načinu rada Opere, u prvom načinu, ažuriranje js-a i CSS-a ovisi o tome na koju je vrijednost opcija Provjeri slike postavljena u postavkama. Ako je opcija postavljena na Uvijek, onda Opera šalje zahtjeve s If-Modified-Since & If-None-Match za provjeru ažuriranja js i css. Ako je vrijednost postavljena, na primjer, 5 sati, tada će se provjeravati u skladu s tim svakih 5 sati ili prisilnim osvježavanjem stranice.

    Drugo, Opera ne provjerava ažuriranje js & CSS (ne pravi GET zahtjeve), a također ne pravi GET zahtjev samoj stranici, odnosno nećemo vidjeti niti ažuriranje js & css niti ažuriranje sadržaja, kao i u drugim slučajevima i u drugim preglednicima. Ali s prisilnim ažuriranjem Opera je bolja. Za razliku od IE & FF, Opera izričito zahtijeva sadržaj stranice bez If-Modified-Since & If-None-Match. Zahtjevi za ažuriranje js-a i CSS-a tijekom prisilnog ažuriranja već dolaze s If-Modified-Since & If-None-Match.

    zaključke
  • Caching je, osim ako ne razumijete točno kako funkcionira u različitim preglednicima i koje su posljedice, prilično opasna stvar.
  • Predmemoriranje se može omogućiti samo ako se stranica rijetko ažurira (odnosno, ako stranica nema stranice koje se ažuriraju u stvarnom vremenu), a čak iu tom slučaju potrebno je postaviti ograničenje na period ograničenja predmemoriranja (npr. , nekoliko sati ili dan)
  • FireFox se, po mom mišljenju, ponaša malo pametnije od IE-a, jer čak i s isključenim predmemoriranjem ne provjerava stalno ažuriranja JavaScripta, što se čini logičnim, jer se JavaScript ažurira vrlo rijetko.
  • Opera vam omogućuje da fleksibilno kontrolirate ažuriranje slika, JavaScripta i CSS-a pomoću postavke Provjeri slike, što je plus. Opera se također ponaša bolje od IE & FF s uključenim predmemoriranjem i prisilnim ažuriranjem, budući da, da vas podsjetim, Opera u ovom slučaju potpuno ažurira sadržaj stranice, a IE & FF će vas ostaviti blaženo nesvjesnima.
  • Sretno vam i profitabilnim stranicama.

    Ispravno konfigurirano predmemoriranje pruža velike prednosti u izvedbi, štedi propusnost i smanjuje troškove poslužitelja, ali mnoga mjesta loše implementiraju predmemoriranje, stvarajući uvjete utrke koji uzrokuju da međusobno povezani resursi ne budu sinkronizirani.

    Velika većina najboljih praksi predmemoriranja spada u jedan od dva obrasca:

    Uzorak br. 1: nepromjenjivi sadržaj i duga predmemorija max-age Cache-Control: max-age=31536000
    • Sadržaj URL-a se ne mijenja, dakle...
    • Preglednik ili CDN mogu lako spremiti resurs u predmemoriju godinu dana
    • Predmemorirani sadržaj koji je mlađi od navedene maksimalne dobi može se koristiti bez savjetovanja s poslužiteljem

    Stranica: Hej, trebam "/script-v1.js", "/styles-v1.css" i "/cats-v1.jpg" 10:24

    Cash: Ja sam prazan, a ti, Server? 10:24

    Poslužitelj: OK, evo ih. Usput, Cash, treba ih koristiti godinu dana, ne više. 10:25

    Gotovina: Hvala! 10:25

    Stranica: Hura! 10:25

    Sljedeći dan

    Stranica: Hej, trebam "/script-v2 .js" , "/styles-v2 .css" i "/cats-v1.jpg" 08:14

    Gotovina: Postoji slika s mačkama, ali ne i ostalo. poslužitelj? 08:14

    Poslužitelj: Jednostavno - evo novog CSS-a i JS-a. Još jednom, gotovina: njihov rok trajanja nije duži od godinu dana. 08:15 sati

    Gotovina: Super! 08:15 sati

    Stranica: Hvala! 08:15 sati

    Gotovina: Hmm, već neko vrijeme nisam koristio "/script-v1.js" & "/styles-v1.css". Vrijeme je da ih uklonite. 12:32

    Koristeći ovaj obrazac, nikada ne mijenjate sadržaj određenog URL-a, mijenjate sam URL:

    Svaki URL ima nešto što se mijenja zajedno sa sadržajem. To može biti broj verzije, datum izmjene ili hash sadržaja (što sam odabrao za svoj blog).

    Većina okvira na strani poslužitelja ima alate koji vam omogućuju da s lakoćom radite ovakve stvari (u Djangu koristim Manifest​Static​Files​Storage); U Node.js također postoje vrlo male biblioteke koje rješavaju iste probleme, na primjer, gulp-rev.

    Međutim, ovaj uzorak nije prikladan za stvari poput članaka i postova na blogu. Njihovim URL-ovima nije moguće odrediti verziju i njihov se sadržaj može promijeniti. Ozbiljno, često imam gramatičke i interpunkcijske pogreške i moram biti u mogućnosti brzo ažurirati sadržaj.

    Uzorak #2: promjenjivi sadržaj koji se uvijek provjerava na poslužitelju Cache-Control: bez predmemorije
    • Sadržaj URL-a će se promijeniti, što znači...
    • Bilo koja lokalno predmemorirana verzija ne može se koristiti bez navođenja poslužitelja.

    Stranica: Hej, trebam sadržaj "/o/" i "/sw.js" 11:32

    Cash: Ne mogu ti pomoći. poslužitelj? 11:32

    Poslužitelj: Ima ih. Gotovina, imajte ih kod sebe, ali pitajte me prije nego ih upotrijebite. 11:33

    Gotovina: Točno! 11:33

    Stranica: Hvala! 11:33

    Sljedeći dan

    Stranica: Hej, trebam ponovno sadržaj "/o/" i "/sw.js" 09:46

    Gotovina: Samo minutu. Server, jesu li moje kopije u redu? Kopija "/o/" je od ponedjeljka, a "/sw.js" je od jučer. 09:46 sati

    Poslužitelj: "/sw.js" nije promijenjen... 09:47

    Gotovina: Cool. Stranica, zadržite "/sw.js" . 09:47 sati

    Poslužitelj: ...ali “/o/” Imam novu verziju. Cash, drži, ali kao prošli put, ne zaboravi me prvo pitati. 09:47 sati

    Gotovina: Shvaćam! 09:47 sati

    Stranica: Sjajno! 09:47 sati

    Napomena: bez predmemoriranja ne znači "ne spremati u predmemoriju", to znači "provjeriti" (ili ponovno potvrditi) predmemorirani resurs na poslužitelju. A no-store govori pregledniku da uopće ne sprema predmemoriju. Također, must-revalidate ne znači obaveznu ponovnu provjeru valjanosti, već da se predmemorirani resurs koristi samo ako je mlađi od specificirane max-age, a samo u suprotnom se ponovno provjerava. Ovako sve počinje s keširanjem ključnih riječi.

    U ovom obrascu odgovoru možemo dodati ETag (identifikator verzije po vašem izboru) ili zaglavlje Last-Modified. Sljedeći put kada klijent zatraži sadržaj, izlazi If-None-Match ili If-Modified-Since, respektivno, dopuštajući poslužitelju da kaže "Upotrijebite ono što imate, vaša predmemorija je ažurna", tj. vrati HTTP 304.

    Ako slanje ETag / Last-Modified nije moguće, poslužitelj uvijek šalje cijeli sadržaj.

    Ovaj uzorak uvijek zahtijeva mrežne pozive, tako da nije tako dobar kao prvi uzorak, koji može raditi bez mrežnih zahtjeva.

    Nije neuobičajeno da nemamo infrastrukturu za prvi uzorak, ali problemi s mrežnim zahtjevima u uzorku 2 mogu se pojaviti i kao rezultat toga, koristi se međuopcija: kratka maksimalna starost i promjenjivi sadržaj. Ovo je loš kompromis.

    Korištenje max-age s promjenjivim sadržajem općenito je pogrešan izbor

    I, nažalost, to je uobičajeno; Github stranice mogu se navesti kao primjer.

    Zamisliti:

    • /članak/
    • /styles.css
    • /script.js

    Sa zaglavljem poslužitelja:

    Cache-Control: obavezna ponovna provjera valjanosti, max-age=600

    • promjene sadržaja URL-a
    • Ako preglednik ima verziju u predmemoriji noviju od 10 minuta, ona se koristi bez konzultacije s poslužiteljem
    • Ako nema takve predmemorije, koristi se mrežni zahtjev, ako je moguće s If-Modified-Since ili If-None-Match

    Stranica: Hej, trebam "/article/", "/script.js" i "/styles.css" 10:21

    Cash: Nemam ništa, kao ti, Server? 10:21

    Poslužitelj: Nema problema, evo ih. Ali zapamti, gotovina: mogu se iskoristiti u sljedećih 10 minuta. 10:22

    Gotovina: Da! 10:22

    Stranica: Hvala! 10:22

    Stranica: Hej, opet trebam "/article/", "/script.js" i "/styles.css" 10:28

    Cash: Ups, žao mi je, ali izgubio sam "/styles.css", ali imam sve ostalo, izvolite. Poslužitelju, možete li prilagoditi "/styles.css" za mene? 10:28

    Poslužitelj: Polako, već se promijenio od kad ste ga prošli put uzeli. Možete ga sigurno koristiti sljedećih 10 minuta. 10:29

    Gotovina: Nema problema. 10:29

    Stranica: Hvala! Ali izgleda da je nešto pošlo po zlu! Sve je polomljeno! Što se događa? 10:29

    Ovaj obrazac ima pravo na život tijekom testiranja, ali kvari sve u stvarnom projektu i vrlo ga je teško pratiti. U gornjem primjeru, poslužitelj je ažurirao HTML, CSS i JS, ali stranica se prikazuje sa starim predmemoriranim HTML-om i JS-om, plus ažuriranim CSS-om s poslužitelja. Neusklađenost verzija sve uništava.

    Često kada napravimo značajne promjene u HTML-u, promijenimo i CSS kako bi ispravno odražavao novu strukturu i JavaScript kako bismo bili u toku sa sadržajem i stilom. Svi ovi resursi su neovisni, ali zaglavlja predmemoriranja to ne mogu izraziti. Kao rezultat toga, korisnici mogu dobiti najnoviju verziju jednog/dva izvora i staru verziju ostalih.

    max-age se postavlja u odnosu na vrijeme odgovora, tako da ako se svi resursi prenesu kao dio jedne adrese, isteći će u isto vrijeme, ali još uvijek postoji mala vjerojatnost desinkronizacije. Ako imate stranice koje ne uključuju JavaScript ili uključuju druge stilove, njihovi datumi isteka predmemorije neće biti sinkronizirani. I što je još gore, preglednik stalno izvlači sadržaj iz predmemorije, ne znajući da su HTML, CSS i JS međusobno ovisni, tako da može sretno povući jednu stvar s popisa i zaboraviti na sve ostalo. Uzimajući u obzir sve ove čimbenike zajedno, trebali biste shvatiti da je vjerojatnost neusklađenih verzija prilično velika.

    Za korisnika, rezultat može biti pokvaren izgled stranice ili drugi problemi. Od malih kvarova do potpuno neupotrebljivog sadržaja.

    Srećom, korisnici imaju izlaz u slučaju nužde...

    Ponekad pomaže osvježavanje stranice

    Ako se stranica učitava osvježavanjem, preglednici uvijek izvode ponovnu provjeru valjanosti na strani poslužitelja, zanemarujući max-age. Stoga, ako je korisniku nešto pokvareno zbog max-age, jednostavno osvježavanje stranice može sve popraviti. Ali, naravno, nakon što se žlice pronađu, talog će i dalje ostati i odnos prema vašoj stranici bit će nešto drugačiji.

    Servisni radnik može produžiti vijek trajanja ovih grešaka

    Na primjer, imate ovakvog servisera:

    Const verzija = "2"; self.addEventListener("install", event => ( event.waitUntil(caches.open(`static-$(version)`) .then(cache => cache.addAll([ "/styles.css", "/script .js" ]))); )); self.addEventListener("aktiviraj", event => ( // ...izbriši stare predmemorije... )); self.addEventListener("fetch", event => ( event.respondWith(caches.match(event.request) .then(response => response || fetch(event.request))); ));

    Ovaj uslužni radnik:

    • sprema skriptu i stilove
    • koristi predmemoriju ako postoji podudaranje, inače pristupa mreži

    Ako promijenimo CSS/JS, također povećavamo broj verzije, što pokreće ažuriranje. Međutim, budući da addAll prvi pristupa predmemoriji, možemo doći u stanje utrke zbog maksimalne dobi i neusklađenih CSS & JS verzija.

    Nakon što su predmemorirani, imat ćemo nekompatibilne CSS & JS do sljedećeg ažuriranja uslužnog radnika - a to je osim ako ponovno ne uđemo u stanje utrke tijekom ažuriranja.

    Možete preskočiti predmemoriranje u uslužnom radniku:

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

    Nažalost, opcije za predmemoriju nisu podržane u Chromeu/Operi i upravo su dodane u noćnu verziju Firefoxa, ali to možete učiniti sami:

    Self.addEventListener("install", event => ( event.waitUntil(caches.open(`static-$(version)`) .then(cache => Promise.all([ "/styles.css", "/script .js" ].map(url => ( // cache-bust korištenjem nasumičnog niza upita return fetch(`$(url)?$(Math.random())`).then(response => ( // neuspjeh na 404, 500 itd. if (!response.ok) throw Error("Not ok"); return cache.put(url, response )) ))));

    U ovom primjeru poništavam predmemoriju koristeći nasumični broj, ali možete ići dalje i dodati hash sadržaja prilikom izgradnje (ovo je slično onome što radi sw-precache). Ovo je neka vrsta implementacije prvog uzorka koji koristi JavaScript, ali radi samo s uslužnim radnikom, ne s preglednicima i CDN-om.

    Servisni radnici i HTTP predmemorija odlično funkcioniraju zajedno, nemojte ih tjerati da se svađaju!

    Kao što vidite, možete zaobići greške u predmemoriranju u svom uslužnom radniku, ali bolje je riješiti korijen problema. Ispravno postavljanje predmemoriranja ne samo da olakšava posao uslužnog radnika, već pomaže i preglednicima koji ne podržavaju uslužnog radnika (Safari, IE/Edge), a također vam omogućuje da izvučete maksimum iz svog CDN-a.

    Ispravna zaglavlja predmemoriranja također mogu znatno olakšati ažuriranje uslužnog radnika.

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

    Ovdje sam predmemorirao korijensku stranicu s uzorkom #2 (ponovna provjera valjanosti na strani poslužitelja) i sve ostale resurse s uzorkom #1 (nepromjenjivi sadržaj). Svako ažuriranje uslužnog radnika uzrokovat će zahtjev za korijensku stranicu, a svi ostali resursi bit će učitani samo ako se njihov URL promijenio. To je dobro jer štedi promet i poboljšava performanse, bez obzira na to nadograđujete li s prethodne ili vrlo stare verzije.

    Ovdje postoji značajna prednost u odnosu na nativnu implementaciju, gdje se cijela binarna datoteka preuzima čak i uz malu promjenu ili uzrokuje složenu binarnu usporedbu. Na taj način možemo ažurirati veliku web aplikaciju s relativno malim opterećenjem.

    Servisni radnici bolje funkcioniraju kao poboljšanje, a ne kao privremena štaka, stoga radite s predmemorijom umjesto da se borite s njom.

    Ako se pažljivo koristi, maksimalna dob i promjenjivi sadržaj mogu biti vrlo dobri

    max-age je vrlo često pogrešan izbor za promjenjivi sadržaj, ali ne uvijek. Na primjer, izvorni članak ima maksimalnu starost od tri minute. Stanje utrke nije problem jer nema ovisnosti o stranici koja koristi isti uzorak predmemoriranja (CSS, JS i slike koriste uzorak #1 - nepromjenjivi sadržaj), sve ostalo ne koristi ovaj obrazac.

    Ovaj obrazac znači da mogu lako napisati popularan članak, a moj CDN (Cloudflare) može ukloniti opterećenje s poslužitelja, sve dok sam spreman čekati tri minute da ažurirani članak bude dostupan korisnicima.

    Ovaj obrazac treba koristiti bez fanatizma. Ako sam članku dodao novi odjeljak i povezao se na njega iz drugog članka, stvorio sam ovisnost koja se mora riješiti. Korisnik može klikom na poveznicu dobiti kopiju članka bez željenog odjeljka. Ako to želim izbjeći, trebao bih osvježiti članak, izbrisati predmemoriranu verziju članka iz Cloudflarea, pričekati tri minute i tek onda dodati poveznicu na drugi članak. Da, ovaj obrazac zahtijeva oprez.

    Kada se koristi ispravno, predmemorija pruža značajna poboljšanja performansi i uštedu propusnosti. Poslužite nepromjenjivi sadržaj ako možete jednostavno promijeniti URL ili upotrijebite ponovnu provjeru valjanosti na strani poslužitelja. Pomiješajte maksimalnu dob i promjenjivi sadržaj ako ste dovoljno hrabri i uvjereni da vaš sadržaj nema ovisnosti koje bi mogle biti neusklađene.

    Uključivanjem vanjskog CSS-a i Javascripta želimo svesti nepotrebne HTTP zahtjeve na minimum.

    U tu svrhu, .js i .css datoteke poslužuju se sa zaglavljima koja osiguravaju pouzdano predmemoriranje.

    Ali što učiniti kada se jedna od ovih datoteka promijeni tijekom razvoja? Svi korisnici imaju staru verziju u svom cacheu - dok cache ne zastari, bit će puno pritužbi na pokvarenu integraciju poslužiteljskog i klijentskog dijela.

    Pravilno predmemorija i verzija u potpunosti eliminiraju ovaj problem i pružaju pouzdanu, transparentnu sinkronizaciju verzija stila/skripte.

    Jednostavno ETag predmemoriranje

    Najjednostavniji način predmemoriranja statičkih resursa je korištenje ETaga.

    Dovoljno je omogućiti odgovarajuću postavku poslužitelja (za Apache je omogućeno prema zadanim postavkama) - i za svaku datoteku u zaglavljima bit će dodan ETag - hash koji ovisi o vremenu ažuriranja, veličini datoteke i (o datoteci baziranoj na inodeu) sustavi) inode.

    Preglednik pohranjuje takvu datoteku u predmemoriju i, na naknadne zahtjeve, navodi zaglavlje If-None-Match s ETagom predmemoriranog dokumenta. Nakon što primi takvo zaglavlje, poslužitelj može odgovoriti s kodom 304 - i tada će dokument biti preuzet iz predmemorije.

    Ovako izgleda:

    Prvi zahtjev poslužitelju (čišćenje predmemorije) GET /misc/pack.js HTTP/1.1 Host: web stranica

    Općenito, preglednik obično dodaje hrpu zaglavlja kao što su User-Agent, Accept itd. Izrezani su radi kratkoće.

    Odgovor poslužitelja Poslužitelj odgovara dokumentom s kodom 200 i ETagom: HTTP/1.x 200 OK Content-Encoding: gzip Content-Type: text/javascript; charset=utf-8 Etag: "3272221997" Accept-Ranges: bytes Content-Length: 23321 Datum: Fri, 02 May 2008 17:22:46 GMT Server: lighttpd Sljedeći zahtjev preglednika Na sljedećem zahtjevu, preglednik dodaje If-None -Podudaranje: (spremljeno u predmemoriju ETag): GET /misc/pack.js HTTP/1.1 Domaćin: stranica If-None-Match: "453700005" Odgovor poslužitelja Poslužitelj izgleda - da, dokument se nije promijenio. To znači da možete izdati kod 304 i ne poslati ponovno dokument. HTTP/1.x 304 Nije izmijenjeno Kodiranje sadržaja: gzip Etag: "453700005" Vrsta sadržaja: tekst/javascript; charset=utf-8 Accept-Ranges: bytes Datum: utorak, 15. travnja 2008. 10:17:11 GMT

    Alternativa je ako se dokument promijenio, tada poslužitelj jednostavno pošalje 200 s novom ETagom.

    Kombinacija Last-Modified + If-Modified-Since funkcionira na sličan način:

  • poslužitelj šalje datum zadnje izmjene u zaglavlju Last-Modified (umjesto ETag)
  • preglednik sprema dokument u predmemoriju, a sljedeći put kada se podnese zahtjev za isti dokument, šalje datum predmemorirane verzije u zaglavlju If-Modified-Since (umjesto If-None-Match)
  • server provjerava datume, i ako dokument nije promijenjen, šalje samo kod 304, bez sadržaja.
  • Ove metode rade pouzdano i dobro, ali preglednik ipak mora napraviti zahtjev za svaku skriptu ili stil.

    Pametno predmemoriranje. Verziranje

    Opći pristup za izradu verzija - ukratko:

  • Verzija (ili datum izmjene) dodaje se svim skriptama. Na primjer, http://site/my.js postat će http://site/my.v1.2.js
  • Sve skripte preglednik čvrsto predmemorira
  • Prilikom ažuriranja skripte, verzija se mijenja u novu: http://site/my.v2.0.js
  • Adresa se promijenila, pa će preglednik ponovo zatražiti i spremiti datoteku u predmemoriju
  • Stara verzija 1.2 postupno će nestati iz predmemorije
  • Teško predmemoriranje

    Teško predmemoriranje- neka vrsta malja koji u potpunosti zabija zahtjeve poslužitelju za predmemorirane dokumente.

    Da biste to učinili, samo dodajte zaglavlja Expires i Cache-Control: max-age.

    Na primjer, za predmemoriju za 365 dana u PHP-u:

    Header("Ističe: ".gmdate("D, d M Y H:i:s", vrijeme()+86400*365)." GMT"); zaglavlje ("Cache-Control: max-age="+86400*365);

    Ili možete trajno spremiti sadržaj u predmemoriju koristeći mod_header u Apacheu:

    Nakon što primi takva zaglavlja, preglednik dugo predmemorira dokument. Sav daljnji pristup dokumentu bit će poslužen izravno iz predmemorije preglednika, bez kontaktiranja poslužitelja.

    Većina preglednika (Opera, Internet Explorer 6+, Safari) NE KEŠIRA dokumente ako u adresi postoji upitnik, jer ih smatraju dinamičnim.

    Zato nazivu datoteke dodajemo verziju. Naravno, s takvim adresama morate koristiti rješenje kao što je mod_rewrite, to ćemo pogledati kasnije u članku.

    P.S. Ali Firefox sprema adrese s upitnicima...

    Automatska rezolucija naziva

    Pogledajmo kako automatski i transparentno mijenjati verzije bez preimenovanja samih datoteka.

    Naziv s verzijom -> Datoteka

    Najjednostavnije je naziv s verzijom pretvoriti u originalni naziv datoteke.

    Na razini Apachea to se može učiniti s mod_rewrite:

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

    Ovo pravilo obrađuje sve css/js/gif/png/jpg datoteke, uklanjajući verziju iz naziva.

    Na primjer:

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

    Ali osim izrezivanja verzije, datotekama morate dodati i zaglavlja tvrdog predmemoriranja. Za to se koriste direktive mod_header:

    Zaglavlje dodaj "Ističe" "Mon, 28 Jul 2014 23:30:00 GMT" Zaglavlje dodaj "Cache-Control" "max-age=315360000"

    I sve zajedno implementira sljedeću Apache konfiguraciju:

    RewriteEngine on # uklanja verziju, a u isto vrijeme postavlja varijablu da je datoteka verzionirana RewriteRule ^/(.*\.)v+\.(css|js|gif|png|jpg)$ /$1$2 # hard cache verzionirane datoteke Zaglavlje dodaj "Ističe" "Mon, 28 Jul 2014 23:30:00 GMT" env=VERSIONED_FILE Zaglavlje dodaj "Cache-Control" "max-age=315360000" env=VERSIONED_FILE

    Zbog načina na koji radi modul mod_rewrite, RewriteRule mora biti postavljen u glavnu konfiguracijsku datoteku httpd.conf ili u uključene (uključene) datoteke, ali ni u kojem slučaju u .htaccess, inače će se prvo pokrenuti naredbe zaglavlja, prije nego što se instalira VERSIONED_FILE varijabla.

    Direktive zaglavlja mogu biti bilo gdje, čak i u .htaccessu - nije važno.

    Automatsko dodavanje verzije nazivu datoteke na HTML stranici

    Kako staviti verziju u ime skripte ovisi o vašem sustavu predložaka i, općenito, o načinu na koji dodajete skripte (stilove, itd.).

    Na primjer, kada koristite datum izmjene kao verziju i Smarty predložak, veze se mogu postaviti ovako:

    Funkcija verzije dodaje verziju:

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

    Rezultat na stranici:

    Optimizacija

    Kako biste izbjegli nepotrebne pozive statistike, možete pohraniti niz s popisom trenutnih verzija u zasebnu varijablu

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

    U ovom slučaju, trenutna verzija iz niza jednostavno se zamjenjuje u HTML.

    Možete ukrstiti oba pristupa i tijekom razvoja proizvesti verziju prema datumu izmjene - za relevantnost, au proizvodnji - verziju iz niza, za performanse.

    Primjenjivost

    Ova metoda predmemoriranja radi posvuda, uključujući Javascript, CSS, slike, Flash filmove itd.

    Korisno je kad god se dokument mijenja, ali preglednik uvijek treba imati trenutnu, ažurnu verziju.

    Ponekad je potrebno spriječiti preglednik da predmemorira stranicu, jer se podaci na njoj svaki put ažuriraju. To može biti generiranje podataka prema odabranim filterima ili drugi sadržaj koji se svaki put kreira na novi način. Ukratko, postoje trenuci kada je potrebno spriječiti podmukli program da pohrani stranicu u predmemoriju. Danas ćemo naučiti kako to implementirati na različite načine, koristeći PHP ili HTML ili .htaccess.

    Zabrana predmemoriranja stranica u HTML-u

    To se može učiniti pomoću meta oznaka. Sada ćemo pogledati različite mogućnosti zabrane predmemoriranja.

    Zabrana predmemoriranja od strane preglednika i proxy poslužitelja

    Onemogući predmemoriranje stranica, samo preglednik

    Postavljanje predmemoriranja za određeno vrijeme za preglednik

    Pomoću donjeg koda možemo reći pregledniku koliko dugo treba zadržati dokument u predmemorij. Nakon toga će se predmemorija ažurirati.

    Postavljanje predmemoriranja za određeno vrijeme za proxy poslužitelj

    Praktično, isto kao u prethodnom kodu, samo je indikacija specifična za proxy poslužitelj.

    Spriječite predmemoriranje stranica pomoću PHP-a

    Praktično, sve je isto kao u slučaju HTML-a, samo što ćemo informacije prikazati kroz zaglavlja zaglavlja. Evo kako implementirati apsolutno odbijanje predmemorije:

    Također možete dopustiti predmemoriju na određeno vrijeme. Na primjer, dopustimo predmemoriranje samo 1 sat.

    Spriječite predmemoriranje stranica pomoću .htaccess

    Kako bi se ideja lakše implementirala, sve se može napraviti na razini konfiguracije Apache poslužitelja. Prije toga moramo provjeriti jesu li potrebni moduli u ispravnom stanju. Otvorite Apache konfiguracijsku datoteku i pogledajte sljedeću sliku:

    LoadModule expires_module modules/mod_expires.so LoadModule headers_module modules/mod_headers.so ... AddModule mod_expires.c AddModule mod_headers.c

    Sada u datoteci .htaccess zapravo zabranjujemo predmemoriranje izlaznih podataka. Kao što znamo, .htaccess datoteka će biti distribuirana u direktorij u kojem se nalazi i u sve poddirektorije.

    # Header Cache-Control Header add Cache-Control "no-store, no-cache, must-revalidate" # Header Expires ExpiresActive On ExpiresDefault "sad"

    Važno je napomenuti da potpuna zabrana predmemoriranja povećava opterećenje poslužitelja. Stoga, igrajte s ovim pažljivo! Još bolje, postavite određeno vrijeme za koje možete spremiti dokumente u predmemoriju. Na primjer, postavimo predmemoriranje na 1 sat:

    # Header Cache-Control Header append Cache-Control "public" # Header Expires ExpiresActive On ExpiresDefault "pristup plus 1 sat"

    Zaključak