Kešování externích stylů a skriptů: věčné a zároveň flexibilní
Stručně navážu na nedávnoý článek GZipování podruhé: skripty a
styly, kde jsem zveřejnil svůj způsob komprese externích CSS a JS
souborů a na základě podnětných připomínek z komentářů ho podstatně
vylepšil. Byl napůl vysloven problém s kešováním pomocí
expires
, a zde přináším intuitivní odpověď
v php kódu.
Jen pro vysvětlenou, v čem spočívá problém: nastavením hlavičky expires dáváme (většinou) prohlížeči na vědomí, jak dlouho se má spokojit s aktuální verzí souboru, jak dlouho si nemá zjišťovat existenci změn (potažmo stahovat ze serveru aktuální verzi). Problém nastává, když v souboru na serveru změny nastanou a zároveň klient o této změně nemá informaci, neboť lhůta dosud nevypršela.
Z této nesladěnosti mohou vyplynout více či méně problematické chyby, obecně známá je například situace, kdy na webu nastane aktualizace jak v HTML kódu, tak v CSS kódu: zatímco HTML obsah je typicky kešován po kratší dobu a se vší pravděpodobností k jeho znovnačtení ze serveru dojde, u CSS se může použít verze z lokální cache. V této situaci klient nevidí web v jeho zamýšlené podobě.
Jak to nyní řeším? (v 1.0)
PHP funkce
function getModStamp ($path) {
return (is_file($path)) ? subStr(md5(fileMTime($path)), 0, 10) : '404-' . $path;
}
Tzn.: Pokud v parametru uvedený soubor existuje → Vezme se
datum poslední změny souboru (unix timestamp) → Datum se zahashuje →
Z hashe se vezme prvních 10 znaků, které se returnují. Pokud soubor
neexistuje → funkce vrátí řetězec 404-zadaná cesta
(pro
snažší debug).
Šablona
<script src="scripts/_zip.php?file=jq.js&<?php echo getModStamp(PATH . '/scripts/jq.js'); ?>" type="text/javascript"></script>
Produkt
<script src="scripts/_zip.php?file=jq.js&b526d9b2b7" type="text/javascript"></script>
Jak mile nastane změna v linkovaném souboru (resp. změní se datum
poslední změny souboru), změní se i generovaný otisk
(b526d9b2b7
), a prohlížeč zareaguje načtením
aktuální verze.
Uznávám, že používání tohoto postupu může být v některých situacích chápáno jako zbytečně pracná metoda a raději se rozhodnete nastavit „optimální“ hodnotu expires. Ale mně to vyhovuje. Mohu takto uživateli posílat soubory s nekonečnou trvanlivostí a zároveň mít jistotu, že jen co provedu sebemenší změnu, bude obratem zaregistrována.
Dodatek: Tuto fičúru oceníte zvláště vy, kdo jste už někdy vysvětloval klientovi, že musí zmáčknout F5 a nebo CTRL-R a ono to né a né…
Komentáře (10)
k formuláři
RSS kanál komentářů
24.12. 2007 — 12:01
Na co ta MD5? Číslo, co vypadne z filemtime by mělo stačit, nebo ne?
Kód v sekci „Šablona“ by šel vylepšit, je v něm zbytečně 2× jméno skriptu. Já bych si asi napsal fci na vygenerování celého tagu, která by to jméno dostala jen jednou jako parametr.
24.12. 2007 — 12:03
Tohle se mi bude určitě hodit, díky.
(nepíše se jak mile dohro mady?)
24.12. 2007 — 17:41
[1] David Majda: – proč MD5? Dobrá otázka :-). Neumím na ni odpovědět.
Kód v šabloně by jistě šel vylepšit, ale v demonstracích dávám přednost pochopitelnosti před estetickými optimalizacemi, ke kterým jednak každý přistupuje odlišně a druhak jejich opodstatnění je znatelné až v kontextu kódu celé šablony…
[2] Peter: – nene, jak mile se píše zvlášť. Prosím neplést s jakmile, které se naopak píše dohromady!
26.12. 2007 — 12:04
Nechca být za rejpala, ptám se je tam něco, co se nedá udělat vhodným nastavením Apache?
Zkoušel jsem si teď hrát s nastavením cachovacích hlaviček a moc se mi to líbí :-) Pokud bude zájem, tak můžu zusit sjet nějaké statistiky.
A sám si odpovím: jo, ušetří se tím několik HTTP dotazů.
26.12. 2007 — 19:33
Ať už tam znamená cokoliv, nevím :-). O statistiky nějak zvlášť nestojím, ale pokud si je budeš dělat pro sebe, tak pošli link ;).
27.12. 2007 — 17:03
Možná by bylo lepší poskytnout radu v jednodušší podobě:
Jakmile se změní CSS, je potřeba změnit mu adresu.
To, že se na změnu adresy používá PHP, je celkem elegantní. Bál bych se ale, že to povede k nějakým chybám. Minimálně doporučuju celou akci důkladně okomentovat, aby bylo každému jasné, co dělá.
Já považuju za jistější osvojit si rutinu:
27.12. 2007 — 19:34
[6] Yuhů: – Ačkoli myslím, že ta funkce je dostatečně sama-o-sobě-mluvící, přidal jsem k ní pro klid duše v dvou větách vysvětlení…
Dále říkáš, že se bojíš chyb. Hm, mohl bys to nějak specifikovat? Neumím si představit představitelnou situaci, kdy by ten skript selhal…
31.12. 2007 — 1:52
Je to moc dobrá věcička. Thx. Ale pořád se nemůžu zbavit dojmu že jakmile se píše dohromady. Jakmile = hned až, kdežto jak mile = jak přívětivě.
31.12. 2007 — 6:26
8 – Bohužel musím nesouhlasit a kontraargumentovat: jsem (podobně jako tento skript) bezchybnatý!
7.1. 2008 — 15:57
[9] Kahi: – Ohledně jak mile zkusim jinou argumentaci…
Bezchybnatý zní jako vodnatelná kedlubna!
Přidat komentář