{"id":15554,"date":"2026-09-05T13:43:45","date_gmt":"2026-09-05T11:43:45","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/narzedzia\/cache-control-revalidation-analyzer\/"},"modified":"2026-09-05T13:43:45","modified_gmt":"2026-09-05T11:43:45","slug":"cache-control-revalidation-analyzer","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/","title":{"rendered":"Analizator Cache-Control i rewalidacji"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">Cache-Control to kr\u00f3tki nag\u0142\u00f3wek z d\u0142ug\u0105 list\u0105 nieporozumie\u0144: no-cache nie znaczy \u201enie zapisuj\u201d, max-age=0 to nie no-store, s-maxage m\u00f3wi tylko do pami\u0119ci dzielonych, a bez \u017cadnego z nich przegl\u0105darka wymy\u015bla czas \u017cycia z Last-Modified. To sprawdzenie pobiera adres z tego serwera, wylicza czas \u015bwie\u017co\u015bci dla przegl\u0105darki i dla pami\u0119ci dzielonej tak, jak robi to RFC 9111, nast\u0119pnie wysy\u0142a \u017c\u0105danie z If-None-Match i jedno z If-Modified-Since, by zobaczy\u0107, czy walidatory naprawd\u0119 dzia\u0142aj\u0105, oraz drugie zwyk\u0142e \u017c\u0105danie, by odczyta\u0107, co pami\u0119\u0107 podr\u0119czna przed serwerem robi za drugim razem.<\/p>\n<div style=\"margin-bottom: 14px;\">\n        <label for=\"cc-url\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Adres (strona, arkusz styl\u00f3w, skrypt, obraz)<\/label><br \/>\n        <input id=\"cc-url\" type=\"text\" value=\"https:\/\/www.wikipedia.org\/\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; box-sizing: border-box; font-family: monospace;\">\n    <\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.82rem; margin-bottom: 16px;\">Z tego serwera pod podany adres trafiaj\u0105 przekierowania i do czterech \u017c\u0105da\u0144 po maksymalnie 256 KB. Hosty w sieciach prywatnych, loopback i link-local s\u0105 odrzucane. Zapytanie chroni reCAPTCHA v3; adres IP wywo\u0142uj\u0105cego i cel s\u0105 przechowywane przez godzin\u0119 w celu ograniczenia cz\u0119stotliwo\u015bci.<\/p>\n<p>    <button id=\"cc-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: var(--on-accent, #0b1114); border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Analiza nag\u0142\u00f3wk\u00f3w pami\u0119ci podr\u0119cznej<\/button><\/p>\n<div id=\"cc-ausgabe\" style=\"margin-top: 22px;\"><\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.8rem; margin: 24px 0 0;\">Granice, o kt\u00f3rych warto wiedzie\u0107: sprawdzany jest tylko jeden z rozwi\u0105zanych adres\u00f3w; CDN odpowiada per w\u0119ze\u0142, wi\u0119c status pami\u0119ci widziany st\u0105d mo\u017ce gdzie indziej si\u0119 r\u00f3\u017cni\u0107; drugie \u017c\u0105danie nast\u0119puje po pierwszym w ci\u0105gu sekund, co pami\u0119\u0107 z minimalnym TTL mo\u017ce traktowa\u0107 inaczej ni\u017c prawdziwy ruch; nag\u0142\u00f3wki ustawiane przez JavaScript lub Service Worker s\u0105 niewidoczne; a heurystyczny czas \u017cycia to sugestia RFC wynosz\u0105ca dziesi\u0119\u0107 procent, poszczeg\u00f3lne przegl\u0105darki maj\u0105 w\u0142asne regu\u0142y.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Cache-Control to kr\u00f3tki nag\u0142\u00f3wek z d\u0142ug\u0105 list\u0105 nieporozumie\u0144: no-cache nie znaczy \u201enie zapisuj\u201d, max-age=0 to nie no-store, s-maxage m\u00f3wi tylko do pami\u0119ci dzielonych, a bez \u017cadnego z nich przegl\u0105darka wymy\u015bla czas \u017cycia z Last-Modified. To sprawdzenie pobiera adres z tego serwera, wylicza czas \u015bwie\u017co\u015bci dla przegl\u0105darki i dla pami\u0119ci dzielonej tak, jak robi to RFC 9111, nast\u0119pnie wysy\u0142a \u017c\u0105danie z If-None-Match i jedno z If-Modified-Since, by zobaczy\u0107, czy walidatory naprawd\u0119 dzia\u0142aj\u0105, oraz drugie zwyk\u0142e \u017c\u0105danie, by odczyta\u0107, co pami\u0119\u0107 podr\u0119czna przed serwerem robi za drugim razem.\",\"label_url\":\"Adres (strona, arkusz styl\u00f3w, skrypt, obraz)\",\"datenschutz\":\"Z tego serwera pod podany adres trafiaj\u0105 przekierowania i do czterech \u017c\u0105da\u0144 po maksymalnie 256 KB. Hosty w sieciach prywatnych, loopback i link-local s\u0105 odrzucane. Zapytanie chroni reCAPTCHA v3; adres IP wywo\u0142uj\u0105cego i cel s\u0105 przechowywane przez godzin\u0119 w celu ograniczenia cz\u0119stotliwo\u015bci.\",\"knopf\":\"Analiza nag\u0142\u00f3wk\u00f3w pami\u0119ci podr\u0119cznej\",\"laeuft\":\"Pobieranie, potem rewalidacja...\",\"grenze\":\"Granice, o kt\u00f3rych warto wiedzie\u0107: sprawdzany jest tylko jeden z rozwi\u0105zanych adres\u00f3w; CDN odpowiada per w\u0119ze\u0142, wi\u0119c status pami\u0119ci widziany st\u0105d mo\u017ce gdzie indziej si\u0119 r\u00f3\u017cni\u0107; drugie \u017c\u0105danie nast\u0119puje po pierwszym w ci\u0105gu sekund, co pami\u0119\u0107 z minimalnym TTL mo\u017ce traktowa\u0107 inaczej ni\u017c prawdziwy ruch; nag\u0142\u00f3wki ustawiane przez JavaScript lub Service Worker s\u0105 niewidoczne; a heurystyczny czas \u017cycia to sugestia RFC wynosz\u0105ca dziesi\u0119\u0107 procent, poszczeg\u00f3lne przegl\u0105darki maj\u0105 w\u0142asne regu\u0142y.\",\"h_verhalten\":\"Co robi z tym pami\u0119\u0107 podr\u0119czna\",\"zeile_url\":\"Zmierzony adres\",\"zeile_ip\":\"Rozwi\u0105zane adresy\",\"zeile_klasse\":\"Zas\u00f3b\",\"zeile_verhalten\":\"Zachowanie w przegl\u0105darce\",\"zeile_browser\":\"\u015awie\u017ce w przegl\u0105darce przez\",\"zeile_geteilt\":\"\u015awie\u017ce w pami\u0119ci dzielonej przez\",\"zeile_dauer\":\"Czas\",\"zeile_limit\":\"Pozosta\u0142e sprawdzenia w tej godzinie\",\"versioniert_zusatz\":\"(wersjonowana nazwa pliku)\",\"klasse_html\":\"dokument HTML\",\"klasse_asset\":\"arkusz styl\u00f3w lub skrypt\",\"klasse_bild\":\"obraz\",\"klasse_schrift\":\"font\",\"klasse_daten\":\"dane (JSON, XML, tekst)\",\"klasse_sonstiges\":\"inne\",\"verhalten_nicht_gespeichert\":\"W og\u00f3le niezapisywane: ka\u017cda wizyta pobiera odpowied\u017a na nowo.\",\"verhalten_heuristisch\":\"Brak czasu \u017cycia i brak walidatora: przegl\u0105darka zgaduje czas \u017cycia z Last-Modified, a bez niego nie zachowuje nic.\",\"verhalten_heuristisch_oder_revalidiert\":\"Brak wyra\u017anego czasu \u017cycia: przegl\u0105darka zgaduje go z Last-Modified, a potem rewaliduje.\",\"verhalten_immer_revalidiert\":\"Zapisane, ale ka\u017cde u\u017cycie najpierw pyta serwer; niezmieniona tre\u015b\u0107 wraca jako kr\u00f3tkie 304.\",\"verhalten_immer_neu\":\"Zapisane, ale ka\u017cde u\u017cycie najpierw pyta serwer, a bez walidatora serwer musi wys\u0142a\u0107 wszystko ponownie.\",\"verhalten_unveraenderlich\":\"Zapisane na ca\u0142y czas \u017cycia i nigdy nie rewalidowane, nawet przy prze\u0142adowaniu.\",\"verhalten_frisch_dann_revalidiert\":\"Podawane z pami\u0119ci podr\u0119cznej przez czas \u017cycia, potem rewalidowane \u017c\u0105daniem warunkowym.\",\"verhalten_frisch_dann_neu\":\"Podawane z pami\u0119ci podr\u0119cznej przez czas \u017cycia, potem pobierane w ca\u0142o\u015bci, bo brak walidatora.\",\"verhalten_unbekannt\":\"Nie do ustalenia, adresu nie da\u0142o si\u0119 pobra\u0107.\",\"quelle_no_store\":\"no-store, nigdy niezapisywane\",\"quelle_private\":\"private, nie dla pami\u0119ci dzielonych\",\"quelle_s_maxage\":\"z s-maxage\",\"quelle_max_age\":\"z max-age\",\"quelle_expires\":\"z Expires\",\"quelle_expires_unlesbar\":\"Expires nieczytelne, liczy si\u0119 jako wygas\u0142e\",\"quelle_heuristisch\":\"heurystycznie, 10 % wieku od Last-Modified\",\"quelle_keine\":\"brak informacji\",\"h_kopf\":\"Nag\u0142\u00f3wki pami\u0119ci podr\u0119cznej, jak wys\u0142ane\",\"h_abrufe\":\"\u017b\u0105dania\",\"spalte_abruf\":\"\u017b\u0105danie\",\"spalte_status\":\"Status\",\"spalte_bytes\":\"Bajty\",\"spalte_ttfb\":\"Pierwszy bajt\",\"spalte_age\":\"Age\",\"spalte_cache\":\"Status pami\u0119ci\",\"abruf_erster\":\"Zwyk\u0142e GET\",\"abruf_inm\":\"Z If-None-Match (ETag)\",\"abruf_ims\":\"Z If-Modified-Since\",\"abruf_zweiter\":\"Zwyk\u0142e GET, drugi raz\",\"abruf_entfaellt\":\"nie wys\u0142ano, pierwsza odpowied\u017a nie mia\u0142a do tego walidatora\",\"fehlgeschlagen\":\"niepowodzenie\",\"h_befunde\":\"Ustalenia\",\"stufe_hoch\":\"Wysoka\",\"stufe_mittel\":\"\u015arednia\",\"stufe_niedrig\":\"Niska\",\"stufe_info\":\"Informacja\",\"stufe_gut\":\"W porz\u0105dku\",\"keine_befunde\":\"Brak uwag.\",\"urteil_gut\":\"Czas \u017cycia i rewalidacja s\u0105 sp\u00f3jne dla tego rodzaju zasobu.\",\"urteil_warnung\":\"Pami\u0119\u0107 podr\u0119czna w zasadzie dzia\u0142a, ale co\u015b kosztuje pobrania albo myli pami\u0119ci.\",\"urteil_kritisch\":\"Adresu nie da\u0142o si\u0119 pobra\u0107.\",\"fehler_kein_token\":\"Sprawdzenie nie mog\u0142o si\u0119 rozpocz\u0105\u0107, poniewa\u017c reCAPTCHA si\u0119 nie za\u0142adowa\u0142a.\",\"fehler_captcha\":\"reCAPTCHA uzna\u0142a \u017c\u0105danie za zautomatyzowane. Zwykle pomaga ponowne za\u0142adowanie strony.\",\"fehler_zu_viele\":\"Osi\u0105gni\u0119to limit {limit} sprawdze\u0144 na godzin\u0119 dla tego adresu.\",\"fehler_adresse\":\"Tego adresu nie da si\u0119 u\u017cy\u0107.\",\"fehler_zu_viele_spruenge\":\"Adres przekierowuje wi\u0119cej ni\u017c pi\u0119\u0107 razy; \u0142a\u0144cuch nie by\u0142 dalej \u015bledzony.\",\"fehler_zaehler\":\"Licznik jest niedost\u0119pny, dlatego nic nie zosta\u0142o sprawdzone.\",\"fehler_pruefdienst\":\"Us\u0142uga reCAPTCHA by\u0142a nieosi\u0105galna.\",\"fehler_aufbau\":\"Us\u0142uga nie jest poprawnie skonfigurowana. B\u0142\u0105d le\u017cy po tej stronie.\",\"fehler_eingabe\":\"\u017b\u0105danie by\u0142o nieczytelne.\",\"fehler_methode\":\"Niew\u0142a\u015bciwa metoda \u017c\u0105dania.\",\"fehler_netz\":\"Us\u0142uga by\u0142a nieosi\u0105galna.\",\"fehler_antwort\":\"Odpowied\u017a by\u0142a nieczytelna.\",\"fehler_unbekannt\":\"Co\u015b posz\u0142o nie tak, a nie ma na to osobnego komunikatu.\",\"grund_leer\":\"Nic nie zosta\u0142o wpisane.\",\"grund_zu_lang\":\"Wpis jest za d\u0142ugi.\",\"grund_unlesbar\":\"To nie jest czytelny adres.\",\"grund_schema\":\"Sprawdzane s\u0105 tylko adresy http i https.\",\"grund_benutzerinfo\":\"Wpisy z danymi logowania s\u0105 odrzucane.\",\"grund_kein_punkt\":\"Nazwa hosta potrzebuje co najmniej jednej kropki.\",\"grund_hostform\":\"Wymagana jest nazwa hosta, nie adres IP.\",\"grund_port\":\"Sprawdzane s\u0105 tylko porty 80, 443, 8080 i 8443.\",\"grund_gesperrter_bereich\":\"Ten host rozwi\u0105zuje si\u0119 do sieci prywatnej lub zarezerwowanej. Takie nigdy nie s\u0105 kontaktowane.\",\"grund_kein_dns\":\"Nazwy hosta nie da si\u0119 rozwi\u0105za\u0107.\",\"grund_abruf\":\"Adres nie odpowiedzia\u0142.\",\"befund_weiterleitung\":\"Przekierowano {n} raz(y) na {ziel} || Analiza dotyczy ko\u0144cowego adresu \u0142a\u0144cucha.\",\"befund_abruf_fehlgeschlagen\":\"Adres nie odpowiada || {fehler}\",\"befund_status_fehler\":\"Serwer odpowiedzia\u0142 statusem {status} || Analizowane s\u0105 nag\u0142\u00f3wki pami\u0119ci podr\u0119cznej odpowiedzi b\u0142\u0119du, nie zamierzonego zasobu. Odpowiedzi b\u0142\u0119d\u00f3w rzadko trafiaj\u0105 do pami\u0119ci, a 404 tylko wtedy, gdy wyra\u017anie na to pozwalaj\u0105.\",\"befund_heuristisch\":\"Brak Cache-Control i Expires: czas \u017cycia zgadni\u0119ty z Last-Modified ({dauer}) || Bez wyra\u017anego czasu \u017cycia pami\u0119\u0107 podr\u0119czna mo\u017ce u\u017cy\u0107 heurystyki; RFC 9111 sugeruje dziesi\u0119\u0107 procent czasu od Last-Modified ({lm}). Przez to czas \u017cycia ro\u015bnie z wiekiem pliku i r\u00f3\u017cni si\u0119 mi\u0119dzy przegl\u0105darkami. Wyra\u017ane max-age zast\u0119puje zgadywanie.\",\"befund_kein_cache_control\":\"Brak Cache-Control i brak Expires || Nic nie m\u00f3wi, jak d\u0142ugo odpowied\u017a mo\u017ce by\u0107 ponownie u\u017cyta, a bez Last-Modified pami\u0119\u0107 podr\u0119czna nie mo\u017ce nawet zgadywa\u0107. Przegl\u0105darki wtedy rewaliduj\u0105 lub pobieraj\u0105 na nowo za ka\u017cdym razem. Rozwi\u0105zaniem jest max-age dopasowane do zasobu.\",\"befund_no_store\":\"no-store || Odpowied\u017a nie mo\u017ce trafi\u0107 do \u017cadnej pami\u0119ci podr\u0119cznej. S\u0142uszne dla tre\u015bci osobistych lub wra\u017cliwych, marnotrawne dla wszystkiego statycznego: ka\u017cda wizyta pobiera na nowo, a przycisk wstecz te\u017c \u0142aduje ponownie.\",\"befund_no_cache\":\"no-cache || Cz\u0119sto \u017ale rozumiane: odpowied\u017a mo\u017ce by\u0107 zapisana, ale ka\u017cde ponowne u\u017cycie musi najpierw zapyta\u0107 serwer. Z walidatorem to tanie 304, bez niego pe\u0142ne pobranie. Aby zabroni\u0107 zapisu, potrzebne jest no-store.\",\"befund_no_store_und_no_cache\":\"no-store razem z no-cache || no-store ju\u017c zabrania zapisu; no-cache na dodatek jest zb\u0119dne. Nieszkodliwe, ale sugeruje, \u017ce dyrektywy skopiowano zamiast wybra\u0107.\",\"befund_max_age_null\":\"max-age=0 || \u015awie\u017ce przez zero sekund, wi\u0119c ka\u017cde ponowne u\u017cycie rewaliduje. W odr\u00f3\u017cnieniu od no-store odpowied\u017a pozostaje zapisana i mo\u017ce by\u0107 potwierdzona przez 304 ({revalidate}). To klasyczne ustawienie dla HTML, kt\u00f3re zawsze musi by\u0107 aktualne, ale przewa\u017cnie si\u0119 nie zmienia.\",\"befund_private\":\"private || Tylko przegl\u0105darka mo\u017ce zapisa\u0107 odpowied\u017a; pami\u0119ci dzielone i CDN-y nie. S\u0142uszne dla stron spersonalizowanych, stracona okazja przy publicznych.\",\"befund_public_ohne_dauer\":\"public bez czasu \u017cycia || public pozwala pami\u0119ciom dzielonym zapisa\u0107 odpowied\u017a, nawet tak\u0105, kt\u00f3ra inaczej by\u0142aby prywatna, ale nic nie m\u00f3wi o czasie. Samo rzadko robi to, co zamierzano.\",\"befund_s_maxage\":\"s-maxage {dauer} dla pami\u0119ci dzielonych, {browser} dla przegl\u0105darek || Pami\u0119ci dzielone, jak CDN, u\u017cywaj\u0105 s-maxage i ignoruj\u0105 max-age; przegl\u0105darki ignoruj\u0105 s-maxage. Dwa czasy \u017cycia dla dw\u00f3ch odbiorc\u00f3w, dok\u0142adnie po to jest ta dyrektywa.\",\"befund_immutable_kurz\":\"immutable z kr\u00f3tkim czasem \u017cycia ({dauer}) || immutable m\u00f3wi przegl\u0105darce, by nie rewalidowa\u0107 nawet przy prze\u0142adowaniu. To ma sens tylko z d\u0142ugim czasem \u017cycia i wersjonowan\u0105 nazw\u0105 pliku; z kr\u00f3tkim prawie nic nie oszcz\u0119dza.\",\"befund_immutable_ohne_version\":\"immutable na nazwie pliku bez wersji || Przegl\u0105darka nie rewaliduje w czasie \u017cycia, nawet przy prze\u0142adowaniu. Je\u015bli plik zmieni si\u0119 pod t\u0105 sam\u0105 nazw\u0105, odwiedzaj\u0105cy zachowuj\u0105 stary do wyga\u015bni\u0119cia. immutable nale\u017cy do nazw z hashem lub wersj\u0105.\",\"befund_immutable_ok\":\"immutable z {dauer} na wersjonowanej nazwie pliku || Przegl\u0105darka trzyma plik przez ca\u0142y czas \u017cycia i pomija \u017c\u0105danie warunkowe przy prze\u0142adowaniu. Tak to jest pomy\u015blane.\",\"befund_swr\":\"stale-while-revalidate {dauer} || Po up\u0142ywie czasu \u017cycia pami\u0119\u0107 mo\u017ce przez tyle podawa\u0107 nie\u015bwie\u017c\u0105 kopi\u0119, pobieraj\u0105c w tle \u015bwie\u017c\u0105. Odwiedzaj\u0105cy nigdy nie czekaj\u0105 na rewalidacj\u0119.\",\"befund_sie\":\"stale-if-error {dauer} || Je\u015bli \u017ar\u00f3d\u0142o zawiedzie, pami\u0119\u0107 mo\u017ce przez tyle dalej podawa\u0107 nie\u015bwie\u017c\u0105 kopi\u0119. Ciche zabezpieczenie na czas awarii.\",\"befund_must_revalidate\":\"must-revalidate przy czasie \u017cycia {dauer} || Po utracie \u015bwie\u017co\u015bci odpowied\u017a nie mo\u017ce by\u0107 podana bez udanej rewalidacji, nawet gdy \u017ar\u00f3d\u0142o jest nieosi\u0105galne. Nie skraca czasu \u017cycia; zabrania tylko podawania nie\u015bwie\u017cych kopii.\",\"befund_pragma\":\"Pragma: no-cache || Relikt HTTP\\\/1.0. Jako nag\u0142\u00f3wek odpowiedzi nie ma okre\u015blonego znaczenia; pami\u0119ci podr\u0119czne kieruj\u0105 si\u0119 Cache-Control. Nieszkodliwe, ale bez skutku.\",\"befund_direktive_unbekannt\":\"Nieznane dyrektywy: {liste} || Pami\u0119ci podr\u0119czne ignoruj\u0105 dyrektywy, kt\u00f3rych nie znaj\u0105. Liter\u00f3wka tutaj po cichu wy\u0142\u0105cza to, co zamierzano.\",\"befund_expires_widerspruch\":\"Expires ({expires}) przeczy max-age ({maxage}) || Gdy s\u0105 oba, wygrywa max-age, a Expires jest ignorowane. Sprzeczno\u015b\u0107 zwykle oznacza, \u017ce dwie warstwy ustawiaj\u0105 je niezale\u017cnie; warto\u015b\u0107 Expires to martwy balast.\",\"befund_expires_unlesbar\":\"Expires nie jest poprawn\u0105 dat\u0105 ({wert}) || Nieczytelne Expires liczy si\u0119 jako ju\u017c wygas\u0142e. Warto\u015bci jak 0 lub -1 to cz\u0119sty spos\u00f3b, by to powiedzie\u0107, ale dyrektywa Cache-Control m\u00f3wi to ja\u015bniej.\",\"befund_expires_vergangen\":\"Expires le\u017cy w przesz\u0142o\u015bci || Odpowied\u017a jest nie\u015bwie\u017ca ju\u017c w chwili nadej\u015bcia i przy ka\u017cdym u\u017cyciu b\u0119dzie rewalidowana lub pobierana na nowo. Bez max-age to jedyna informacja o czasie \u017cycia.\",\"befund_expires_allein\":\"Czas \u017cycia tylko z Expires ({dauer}) || Dzia\u0142a, ale Expires to czas bezwzgl\u0119dny i zale\u017cy od zgodno\u015bci zegar\u00f3w serwera i klienta. max-age jest wzgl\u0119dne i na to odporne.\",\"befund_date_abweichung\":\"Zegar serwera r\u00f3\u017cni si\u0119 od zegara tego serwera o {sekunden} s || Obliczenia Expires i Age zale\u017c\u0105 od nag\u0142\u00f3wka Date. Rozje\u017cd\u017caj\u0105cy si\u0119 zegar serwera skraca lub wyd\u0142u\u017ca ka\u017cdy czas \u017cycia liczony z czas\u00f3w bezwzgl\u0119dnych.\",\"befund_date_fehlt\":\"Brak nag\u0142\u00f3wka Date || Serwery \u017ar\u00f3d\u0142owe musz\u0105 go wysy\u0142a\u0107. Bez niego pami\u0119ci podr\u0119czne u\u017cywaj\u0105 w\u0142asnego zegara, a Expires nie da si\u0119 wiarygodnie zinterpretowa\u0107.\",\"befund_validator_fehlt\":\"Brak ETag i brak Last-Modified || Po up\u0142ywie czasu \u017cycia przegl\u0105darka nie mo\u017ce zapyta\u0107, czy tre\u015b\u0107 si\u0119 zmieni\u0142a; musi pobra\u0107 wszystko ponownie. Last-Modified lub ETag zamienia to w 304 bez tre\u015bci.\",\"befund_etag_schwach\":\"S\u0142aby ETag ({etag}) || W\\\/ oznacza walidator obiecuj\u0105cy r\u00f3wnowa\u017cno\u015b\u0107 semantyczn\u0105, nie bajt po bajcie. W porz\u0105dku do rewalidacji; nieu\u017cyteczny do \u017c\u0105da\u0144 zakresowych.\",\"befund_last_modified_unlesbar\":\"Last-Modified nie jest poprawn\u0105 dat\u0105 ({wert}) || Klienci ignoruj\u0105 nieczytelny walidator, wi\u0119c \u017c\u0105dania warunkowe oparte na nim nigdy nie nast\u0119puj\u0105.\",\"befund_last_modified_zukunft\":\"Last-Modified le\u017cy w przysz\u0142o\u015bci ({wert}) || Czas modyfikacji p\u00f3\u017aniejszy ni\u017c teraz wskazuje na z\u0142y zegar serwera. Pami\u0119ci podr\u0119czne traktuj\u0105 go jak czas bie\u017c\u0105cy; oparte na nim heurystyki si\u0119 za\u0142amuj\u0105.\",\"befund_etag_304\":\"If-None-Match odpowiedzia\u0142o 304 || ETag dzia\u0142a: niezmieniony zas\u00f3b kosztuje kilka bajt\u00f3w nag\u0142\u00f3wk\u00f3w zamiast {bytes} bajt\u00f3w.\",\"befund_etag_kein_304\":\"If-None-Match odpowiedzia\u0142o 200, nie 304 || Serwer wys\u0142a\u0142 ETag ({etag}), ale nie rozpozna\u0142 go w \u017c\u0105daniu warunkowym; ca\u0142a tre\u015b\u0107 przysz\u0142a ponownie. Apache z mod_deflate to klasyczna przyczyna: dokleja -gzip do ETag, a potem nie dopasowuje w\u0142asnego sufiksu (DeflateAlterETag). CDN-y przepisuj\u0105ce ETag robi\u0105 to samo.\",\"befund_etag_status\":\"If-None-Match odpowiedzia\u0142o {status} || Ani 200, ani 304; \u017c\u0105danie warunkowe potraktowano jako co\u015b innego.\",\"befund_ims_304\":\"If-Modified-Since odpowiedzia\u0142o 304 || Walidator oparty na dacie dzia\u0142a.\",\"befund_ims_kein_304\":\"If-Modified-Since odpowiedzia\u0142o 200, nie 304 || Serwer wysy\u0142a Last-Modified, ale nie honoruje go w \u017c\u0105daniu warunkowym. Z dzia\u0142aj\u0105cym ETag nic to nie kosztuje; bez niego ka\u017cda rewalidacja to pe\u0142ne pobranie.\",\"befund_304_mit_inhalt\":\"304 z tre\u015bci\u0105 {bytes} bajt\u00f3w || 304 nie mo\u017ce nie\u015b\u0107 tre\u015bci. Klienci j\u0105 ignoruj\u0105, ale bajty i tak s\u0105 przesy\u0142ane, a niekt\u00f3re w\u0119z\u0142y po\u015brednie si\u0119 na tym potykaj\u0105.\",\"befund_etag_wechselt\":\"ETag zmienia si\u0119 mi\u0119dzy dwoma identycznymi \u017c\u0105daniami || Pierwsza odpowied\u017a nios\u0142a {a}, warunkowa {b}. Walidator zmieniaj\u0105cy si\u0119 przy ka\u017cdym \u017c\u0105daniu nigdy nie pasuje, wi\u0119c \u017c\u0105dania warunkowe zawsze zawodz\u0105. Typowe przyczyny: ETag zbudowany ze znacznika czasu lub z tokenu per \u017c\u0105danie.\",\"befund_vary_stern\":\"Vary: * || Odpowied\u017a zale\u017cy od czego\u015b spoza nag\u0142\u00f3wk\u00f3w \u017c\u0105dania; pami\u0119ci podr\u0119czne musz\u0105 traktowa\u0107 ka\u017cde \u017c\u0105danie jako inne. Dla pami\u0119ci dzielonych praktycznie niezapisywalne.\",\"befund_vary_user_agent\":\"Vary: User-Agent || Przy tysi\u0105cach r\u00f3\u017cnych ci\u0105g\u00f3w User-Agent pami\u0119\u0107 dzielona trzyma kopi\u0119 na ka\u017cdy ci\u0105g i prawie nigdy nie trafia. Client hints albo brak Vary spe\u0142niaj\u0105 ten sam cel bez rozdrobnienia.\",\"befund_vary_cookie\":\"Vary: Cookie || Ka\u017cda inna warto\u015b\u0107 cookie dostaje w\u0142asny wpis w pami\u0119ci. Je\u015bli strona dodatkowo ustawia cookie per odwiedzaj\u0105cy, pami\u0119\u0107 nigdy nie trafia dla drugiego odwiedzaj\u0105cego.\",\"befund_set_cookie_geteilt\":\"Set-Cookie na odpowiedzi, kt\u00f3r\u0105 pami\u0119ci dzielone mog\u0105 trzyma\u0107 przez {dauer} || Pami\u0119\u0107, kt\u00f3ra zapisze t\u0119 odpowied\u017a, zapisze z ni\u0105 cookie i poda cookie jednego odwiedzaj\u0105cego nast\u0119pnemu. Wi\u0119kszo\u015b\u0107 CDN-\u00f3w z tego powodu w og\u00f3le nie zapisuje odpowiedzi z Set-Cookie, wi\u0119c zamierzone s-maxage te\u017c nie nast\u0119puje. Albo usun\u0105\u0107 cookie, albo oznaczy\u0107 odpowied\u017a jako private.\",\"befund_cache_davor\":\"Przed \u017ar\u00f3d\u0142em stoi pami\u0119\u0107 podr\u0119czna ({system}) || Pierwsze \u017c\u0105danie: {status1}, Age {age1}; drugie \u017c\u0105danie: {status2}, Age {age2}. Age liczy sekundy, przez kt\u00f3re kopia le\u017cy w pami\u0119ci.\",\"befund_cache_trifft\":\"Pami\u0119\u0107 przed \u017ar\u00f3d\u0142em trafia ({status}) || Odpowied\u017a przysz\u0142a z pami\u0119ci podr\u0119cznej, nie ze \u017ar\u00f3d\u0142a. Odwiedzaj\u0105cy dostaj\u0105 j\u0105 bez pracy \u017ar\u00f3d\u0142a.\",\"befund_cache_trifft_nicht\":\"Pami\u0119\u0107 przed \u017ar\u00f3d\u0142em tego nie zapisuje ({status}) || Oba \u017c\u0105dania posz\u0142y do \u017ar\u00f3d\u0142a. Dla HTML za CDN to zwyk\u0142e ustawienie domy\u015blne; zasoby statyczne powinny trafia\u0107.\",\"befund_age_ueber_frische\":\"Age {age} s przekracza czas \u017cycia {frische} s || Pami\u0119\u0107 poda\u0142a kopi\u0119, kt\u00f3ra wed\u0142ug w\u0142asnych nag\u0142\u00f3wk\u00f3w jest ju\u017c nie\u015bwie\u017ca. Albo pami\u0119\u0107 stosuje w\u0142asne regu\u0142y, albo dzia\u0142a stale-while-revalidate.\",\"befund_html_lang\":\"HTML w pami\u0119ci przez {dauer} bez rewalidacji || Odwiedzaj\u0105cy mog\u0105 przez tyle widzie\u0107 nieaktualn\u0105 stron\u0119 po zmianie, a poprawki nie da si\u0119 do nich przepchn\u0105\u0107. Kr\u00f3tkie max-age z must-revalidate albo max-age=0 z walidatorem utrzymuje HTML aktualnym niskim kosztem.\",\"befund_html_kurz\":\"HTML \u015bwie\u017ce przez {dauer}, potem rewalidowane || Kr\u00f3tki czas \u017cycia poch\u0142ania serie powt\u00f3rzonych \u017c\u0105da\u0144, a zmiany szybko docieraj\u0105 do odwiedzaj\u0105cych.\",\"befund_html_revalidiert\":\"HTML rewalidowane przy ka\u017cdym u\u017cyciu || Przegl\u0105darka trzyma kopi\u0119 i za ka\u017cdym razem pyta serwer; niezmienione strony wracaj\u0105 jako 304. Zmiany docieraj\u0105 do odwiedzaj\u0105cych natychmiast.\",\"befund_asset_lang_versioniert\":\"Wersjonowany zas\u00f3b w pami\u0119ci przez {dauer} || D\u0142ugi czas \u017cycia na nazwie pliku zmieniaj\u0105cej si\u0119 z tre\u015bci\u0105 to przypadek idealny: rok w pami\u0119ci, wymiana w chwili, gdy HTML wska\u017ce now\u0105 nazw\u0119.\",\"befund_asset_lang_unversioniert\":\"D\u0142ugi czas \u017cycia ({dauer}) na niewersjonowanej nazwie pliku || Zmiana pod t\u0105 sam\u0105 nazw\u0105 dociera do powracaj\u0105cych odwiedzaj\u0105cych dopiero po wyga\u015bni\u0119ciu kopii. Albo doda\u0107 hash lub wersj\u0119 do nazwy, albo skr\u00f3ci\u0107 czas \u017cycia.\",\"befund_asset_kurz\":\"Kr\u00f3tki czas \u017cycia zasobu statycznego ({dauer}) || Arkusze styl\u00f3w, skrypty, obrazy i fonty zmieniaj\u0105 si\u0119 rzadko; czas \u017cycia poni\u017cej doby oznacza cz\u0119st\u0105 rewalidacj\u0119 bez korzy\u015bci. Z wersjonowan\u0105 nazw\u0105 rok jest norm\u0105.\",\"befund_asset_mittel\":\"Zas\u00f3b w pami\u0119ci przez {dauer} || Droga po\u015brednia: mniej rewalidacji ni\u017c przy kr\u00f3tkim czasie \u017cycia, nadal ograniczone ryzyko nie\u015bwie\u017cych kopii.\",\"befund_asset_ungecached\":\"Zas\u00f3b statyczny bez pami\u0119ci podr\u0119cznej ({quelle}) || Ka\u017cde wy\u015bwietlenie strony pobiera ten plik ponownie. max-age, najlepiej z wersjonowan\u0105 nazw\u0105, ca\u0142kowicie usuwa te pobrania.\",\"befund_versioniert_aber_kurz\":\"Wersjonowana nazwa pliku, ale tylko {dauer} czasu \u017cycia || Nazwa ju\u017c zmienia si\u0119 z tre\u015bci\u0105, wi\u0119c d\u0142ugi czas \u017cycia nie niesie ryzyka. Kr\u00f3tki marnuje korzy\u015b\u0107 z wersjonowania.\"};<\/p>\n<p>    var ENDPUNKT = '\/lw-cachecheck.php';\n    var SITEKEY = '6LcrPkEtAAAAAPo1QCOf-IIM2fCL0UfdJz4y2iSY';\n    var STUFEN = ['hoch', 'mittel', 'niedrig', 'info', 'gut'];\n    var ABRUFE = ['erster', 'inm', 'ims', 'zweiter'];\n    var KLASSEN = ['html', 'asset', 'bild', 'schrift', 'daten', 'sonstiges'];\n    var VERHALTEN = ['nicht_gespeichert', 'heuristisch', 'heuristisch_oder_revalidiert', 'immer_revalidiert', 'immer_neu', 'unveraenderlich', 'frisch_dann_revalidiert', 'frisch_dann_neu', 'unbekannt'];\n    var QUELLEN = ['no-store', 'private', 's-maxage', 'max-age', 'expires', 'expires-unlesbar', 'heuristisch', 'keine'];\n    var KOPF_REIHE = ['cache-control', 'expires', 'date', 'last-modified', 'etag', 'age', 'vary', 'pragma', 'surrogate-control', 'cdn-cache-control', 'cloudflare-cdn-cache-control', 'cf-cache-status', 'x-cache', 'x-cache-hits', 'x-cache-enabled', 'x-served-by', 'via', 'x-varnish', 'x-litespeed-cache', 'x-nginx-cache', 'x-proxy-cache', 'x-drupal-cache', 'x-cache-status', 'set-cookie', 'content-type', 'server'];<\/p>\n<p>    function liste(w) { return Array.isArray(w) ? w : []; }\n    function zahl(w) { return (typeof w === 'number' && isFinite(w)) ? w : null; }\n    function text(schluessel, daten) {\n        var t = T[schluessel];\n        if (typeof t !== 'string') { return null; }\n        return t.replace(\/\\{([a-z_0-9]+)\\}\/g, function (m, k) {\n            return (daten && daten[k] !== undefined && daten[k] !== null) ? String(daten[k]) : m;\n        });\n    }\n    function quelleText(q) { var t = T['quelle_' + String(q || 'keine').replace(\/-\/g, '_')]; return typeof t === 'string' ? t : String(q); }<\/p>\n<p>    function abruf(r) {\n        if (!r || typeof r !== 'object') { return null; }\n        return { ok: !!r.ok, status: zahl(r.status), fehler: r.fehler ? String(r.fehler) : null, bytes: zahl(r.bytes), ttfb: zahl(r.ttfb_ms), gesamt: zahl(r.gesamt_ms), age: zahl(r.age), cacheStatus: r.cache_status ? String(r.cache_status) : null };\n    }\n    function frische(f) {\n        f = (f && typeof f === 'object') ? f : {};\n        return { sekunden: zahl(f.sekunden), quelle: QUELLEN.indexOf(f.quelle) === -1 ? 'keine' : f.quelle, text: f.text ? String(f.text) : '-' };\n    }<\/p>\n<p>    function bewerten(antwort) {\n        var a = antwort || {};\n        if (a.fehler) { return { fehler: String(a.fehler), grund: a.grund || null, limit: zahl(a.limit), kette: liste(a.kette) }; }\n        var befunde = liste(a.befunde).map(function (f) {\n            return { key: String(f.key || ''), stufe: STUFEN.indexOf(f.stufe) === -1 ? 'info' : f.stufe, daten: (f.daten && typeof f.daten === 'object') ? f.daten : {} };\n        });\n        var gruppen = {};\n        STUFEN.forEach(function (s) { gruppen[s] = befunde.filter(function (f) { return f.stufe === s; }); });\n        var abrufe = {};\n        ABRUFE.forEach(function (v) { abrufe[v] = abruf(a.abrufe ? a.abrufe[v] : null); });\n        var kopf = {};\n        if (a.kopf && typeof a.kopf === 'object') { Object.keys(a.kopf).forEach(function (k) { if (typeof a.kopf[k] === 'string') { kopf[k.toLowerCase()] = a.kopf[k]; } }); }\n        return {\n            fehler: null, url: a.url ? String(a.url) : '', host: a.host ? String(a.host) : '', ip: a.ip ? String(a.ip) : '', ips: liste(a.ips),\n            urteil: (a.urteil === 'gut' || a.urteil === 'warnung' || a.urteil === 'kritisch') ? a.urteil : 'kritisch',\n            klasse: KLASSEN.indexOf(a.klasse) === -1 ? 'sonstiges' : a.klasse, versioniert: !!a.versioniert,\n            verhalten: VERHALTEN.indexOf(a.verhalten) === -1 ? 'unbekannt' : a.verhalten,\n            browser: frische(a.browser), geteilt: frische(a.geteilt),\n            direktiven: (a.direktiven && typeof a.direktiven === 'object') ? Object.keys(a.direktiven) : [],\n            kopf: kopf, abrufe: abrufe, befunde: befunde, gruppen: gruppen,\n            kette: liste(a.kette), dauer: zahl(a.dauer_ms), limitRest: zahl(a.limit_rest)\n        };\n    }<\/p>\n<p>    function skriptLaden() {\n        return new Promise(function (auf) {\n            if (window.grecaptcha) { auf(true); return; }\n            var s = document.createElement('script');\n            s.src = 'https:\/\/www.google.com\/recaptcha\/api.js?render=' + SITEKEY;\n            s.onload = function () { auf(true); }; s.onerror = function () { auf(false); };\n            document.head.appendChild(s);\n            setTimeout(function () { auf(!!window.grecaptcha); }, 8000);\n        });\n    }\n    function tokenHolen() {\n        return skriptLaden().then(function (da) {\n            if (!da || !window.grecaptcha || !window.grecaptcha.ready) { return null; }\n            return new Promise(function (auf) {\n                var fertig = false;\n                function einmal(w) { if (!fertig) { fertig = true; auf(w); } }\n                setTimeout(function () { einmal(null); }, 12000);\n                try {\n                    window.grecaptcha.ready(function () {\n                        if (fertig) { return; }\n                        if (!window.grecaptcha.execute) { einmal(null); return; }\n                        window.grecaptcha.execute(SITEKEY, { action: 'cachecheck' }).then(function (t) { einmal(t || null); }, function () { einmal(null); });\n                    });\n                } catch (e) { einmal(null); }\n            });\n        }, function () { return null; });\n    }\n    function abfragen(url) {\n        return tokenHolen().then(function (token) {\n            return fetch(ENDPUNKT, { method: 'POST', headers: { 'Content-Type': 'application\/json' }, body: JSON.stringify({ url: url, token: token || '' }) })\n                .then(function (r) { return r.json().then(function (j) { return j; }, function () { return { fehler: 'antwort' }; }); }, function () { return { fehler: 'netz' }; });\n        });\n    }<\/p>\n<p>    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.CC = { bewerten: bewerten, darstellen: null, text: text, quelleText: quelleText, ENDPUNKT: ENDPUNKT, STUFEN: STUFEN, ABRUFE: ABRUFE, KLASSEN: KLASSEN, VERHALTEN: VERHALTEN, QUELLEN: QUELLEN, T: T };<\/p>\n<p>    var btn = document.getElementById('cc-btn');\n    var out = document.getElementById('cc-ausgabe');\n    if (!btn || !out) { return; }<\/p>\n<p>    function el(tag, stil, txt) { var e = document.createElement(tag); if (stil) { e.setAttribute('style', stil); } if (txt !== undefined && txt !== null) { e.textContent = txt; } return e; }\n    function wert(id) { var e = document.getElementById(id); return e ? e.value : ''; }\n    var UEBERSCHRIFT = 'font-family: \"Nunito Sans\", sans-serif; font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 22px 0 8px;';\n    var ZELLE = 'padding: 5px 12px 5px 0; color: var(--text-secondary, #a0a0b0); font-size: 0.87rem;';\n    var ZELLE_WERT = 'padding: 5px 12px 5px 0; color: var(--text-primary, #e8e8ee); font-size: 0.87rem; font-family: monospace; word-break: break-all;';\n    var KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 8px; padding: 14px 16px; margin: 0 0 10px;';\n    var GUT = ' color: #7ee787;', WARN = ' color: #ffa94d;', ROT = ' color: #ff7b72;', GRAU = ' color: #8a8a99;';\n    var FARBEN = { hoch: '#ff7b72', mittel: '#ffa94d', niedrig: '#e3b341', info: '#8a8a99', gut: '#7ee787' };\n    var URTEIL = { gut: GUT, warnung: WARN, kritisch: ROT };\n    function gitter(sp) { return el('div', 'display: grid; grid-template-columns: ' + sp + '; gap: 0 18px; align-items: baseline;'); }\n    function paar(g, n, w, stil) { g.appendChild(el('div', ZELLE, n)); g.appendChild(el('div', ZELLE_WERT + (stil || ''), w)); }\n    function ms(v) { return v === null ? '-' : v + ' ms'; }<\/p>\n<p>    function darstellen(b, ziel) {\n        ziel.innerHTML = '';\n        if (b.fehler) {\n            var txt = T['fehler_' + b.fehler] || T.fehler_unbekannt;\n            if (b.grund && T['grund_' + b.grund]) { txt = txt + ' ' + T['grund_' + b.grund]; }\n            if (b.limit !== null) { txt = txt.replace('{limit}', String(b.limit)); }\n            ziel.appendChild(el('p', ZELLE + WARN + ' margin: 0;', txt));\n            return;\n        }\n        ziel.appendChild(el('div', 'font-size: 1.05rem; font-weight: 700; margin: 0 0 12px;' + URTEIL[b.urteil], T['urteil_' + b.urteil]));<\/p>\n<p>        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_verhalten));\n        var g = gitter('auto auto');\n        paar(g, T.zeile_url, b.url);\n        paar(g, T.zeile_ip, b.ips.length ? b.ips.join(', ') : b.ip, GRAU);\n        paar(g, T.zeile_klasse, T['klasse_' + b.klasse] + (b.versioniert ? ' ' + T.versioniert_zusatz : ''), GRAU);\n        paar(g, T.zeile_verhalten, T['verhalten_' + b.verhalten], b.verhalten === 'unveraenderlich' || b.verhalten === 'frisch_dann_revalidiert' || b.verhalten === 'immer_revalidiert' ? GUT : (b.verhalten === 'heuristisch' || b.verhalten === 'immer_neu' ? WARN : ''));\n        paar(g, T.zeile_browser, b.browser.text + '  (' + quelleText(b.browser.quelle) + ')', b.browser.sekunden === null ? WARN : '');\n        paar(g, T.zeile_geteilt, b.geteilt.text + '  (' + quelleText(b.geteilt.quelle) + ')', b.geteilt.sekunden === null ? WARN : '');\n        if (b.dauer !== null) { paar(g, T.zeile_dauer, ms(b.dauer), GRAU); }\n        if (b.limitRest !== null) { paar(g, T.zeile_limit, String(b.limitRest), GRAU); }\n        ziel.appendChild(g);<\/p>\n<p>        var kopfKeys = KOPF_REIHE.filter(function (k) { return typeof b.kopf[k] === 'string'; });\n        if (kopfKeys.length) {\n            ziel.appendChild(el('div', UEBERSCHRIFT, T.h_kopf));\n            var gk = gitter('auto auto');\n            kopfKeys.forEach(function (k) { paar(gk, k, b.kopf[k], k === 'cache-control' ? '' : GRAU); });\n            ziel.appendChild(gk);\n        }<\/p>\n<p>        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_abrufe));\n        var huelle = el('div', 'overflow-x: auto;');\n        var gp = gitter('auto auto auto auto auto auto');\n        [T.spalte_abruf, T.spalte_status, T.spalte_bytes, T.spalte_ttfb, T.spalte_age, T.spalte_cache].forEach(function (s) { gp.appendChild(el('div', ZELLE + ' font-weight: 700; color: var(--text-primary, #e8e8ee); white-space: nowrap;', s)); });\n        ABRUFE.forEach(function (v) {\n            var r = b.abrufe[v];\n            gp.appendChild(el('div', ZELLE + ' white-space: nowrap;', T['abruf_' + v]));\n            if (r === null) { gp.appendChild(el('div', ZELLE_WERT + GRAU + ' grid-column: span 5;', T.abruf_entfaellt)); return; }\n            if (!r.ok) { gp.appendChild(el('div', ZELLE_WERT + ROT + ' grid-column: span 5; white-space: normal;', T.fehlgeschlagen + (r.fehler ? ' (' + r.fehler + ')' : ''))); return; }\n            gp.appendChild(el('div', ZELLE_WERT + (r.status === 304 ? GUT : ''), String(r.status)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, r.bytes === null ? '-' : String(r.bytes)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, ms(r.ttfb)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, r.age === null ? '-' : String(r.age)));\n            gp.appendChild(el('div', ZELLE_WERT + (r.cacheStatus && \/^(hit|stale|revalidated|updating)\/i.test(r.cacheStatus) ? GUT : GRAU), r.cacheStatus || '-'));\n        });\n        huelle.appendChild(gp);\n        ziel.appendChild(huelle);<\/p>\n<p>        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_befunde));\n        var irgendwas = false;\n        STUFEN.forEach(function (s) {\n            var gr = b.gruppen[s];\n            if (!gr.length) { return; }\n            irgendwas = true;\n            ziel.appendChild(el('div', 'font-weight: 700; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.5px; margin: 14px 0 6px; color: ' + FARBEN[s] + ';', T['stufe_' + s] + ' (' + gr.length + ')'));\n            gr.forEach(function (f) {\n                var k = el('div', KASTEN + ' border-left: 3px solid ' + FARBEN[s] + ';');\n                var t = text('befund_' + f.key, f.daten) || f.key;\n                var teile = t.split(' || ');\n                k.appendChild(el('div', 'color: var(--text-primary, #e8e8ee); font-size: 0.9rem; font-weight: 700;', teile[0]));\n                if (teile[1]) { k.appendChild(el('div', ZELLE + ' padding: 6px 0 0; line-height: 1.55;', teile[1])); }\n                ziel.appendChild(k);\n            });\n        });\n        if (!irgendwas) { ziel.appendChild(el('p', ZELLE + ' margin: 0;', T.keine_befunde)); }\n    }\n    window.LW_TEST.CC.darstellen = darstellen;<\/p>\n<p>    var laeuft = false;\n    btn.addEventListener('click', function () {\n        if (laeuft) { return; }\n        laeuft = true; btn.disabled = true;\n        out.innerHTML = '';\n        out.appendChild(el('p', ZELLE + GRAU + ' margin: 0;', T.laeuft));\n        abfragen(wert('cc-url')).then(function (a) { darstellen(bewerten(a), out); laeuft = false; btn.disabled = false; },\n            function () { darstellen(bewerten({ fehler: 'netz' }), out); laeuft = false; btn.disabled = false; });\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Odczytuje nag\u0142\u00f3wki pami\u0119ci podr\u0119cznej adresu, wylicza, jak d\u0142ugo przegl\u0105darka i pami\u0119\u0107 dzielona mog\u0105 trzyma\u0107 odpowied\u017a i na jakiej podstawie, wysy\u0142a \u017c\u0105dania warunkowe, by sprawdzi\u0107, czy ETag i Last-Modified naprawd\u0119 daj\u0105 304, oraz sprawdza, czy CDN lub pami\u0119\u0107 stron przed serwerem trafia.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9284,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92229,92310,92283],"class_list":["post-15554","page","type-page","status-publish","hentry","tag-devops-pl","tag-networking-pl","tag-web-performance-pl"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Analizator Cache-Control i rewalidacji - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Analizator Cache-Control i rewalidacji - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Odczytuje nag\u0142\u00f3wki pami\u0119ci podr\u0119cznej adresu, wylicza, jak d\u0142ugo przegl\u0105darka i pami\u0119\u0107 dzielona mog\u0105 trzyma\u0107 odpowied\u017a i na jakiej podstawie, wysy\u0142a \u017c\u0105dania warunkowe, by sprawdzi\u0107, czy ETag i Last-Modified naprawd\u0119 daj\u0105 304, oraz sprawdza, czy CDN lub pami\u0119\u0107 stron przed serwerem trafia.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/cache-control-revalidation-analyzer\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/cache-control-revalidation-analyzer\\\/\",\"name\":\"Analizator Cache-Control i rewalidacji - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-05T11:43:45+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/cache-control-revalidation-analyzer\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/cache-control-revalidation-analyzer\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/cache-control-revalidation-analyzer\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/toolbox-3\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Analizator Cache-Control i rewalidacji\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Analizator Cache-Control i rewalidacji - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/","og_locale":"en_US","og_type":"article","og_title":"Analizator Cache-Control i rewalidacji - Lukas Wojcik - Blog","og_description":"Odczytuje nag\u0142\u00f3wki pami\u0119ci podr\u0119cznej adresu, wylicza, jak d\u0142ugo przegl\u0105darka i pami\u0119\u0107 dzielona mog\u0105 trzyma\u0107 odpowied\u017a i na jakiej podstawie, wysy\u0142a \u017c\u0105dania warunkowe, by sprawdzi\u0107, czy ETag i Last-Modified naprawd\u0119 daj\u0105 304, oraz sprawdza, czy CDN lub pami\u0119\u0107 stron przed serwerem trafia.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/","og_site_name":"Lukas Wojcik - Blog","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/","name":"Analizator Cache-Control i rewalidacji - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-05T11:43:45+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/cache-control-revalidation-analyzer\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/toolbox-3\/"},{"@type":"ListItem","position":3,"name":"Analizator Cache-Control i rewalidacji"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/15554","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=15554"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/15554\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9284"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=15554"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=15554"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}