Dokumentacja

Zapisuj pliki w pamięci podręcznej przeglądarki

Zapisuj pliki w pamięci podręcznej przeglądarki

Każda podstrona ładuje te same arkusze stylów, skrypty, logotypy i czcionki. Bez nagłówka pamięci podręcznej przeglądarka pobiera je ponownie przy każdej wizycie i przy każdym kliknięciu w kolejną podstronę: więcej żądań, wolniejsze strony dla powracających odwiedzających i większy ruch na Twoim serwerze. Nagłówek Cache-Control mówi przeglądarce, że może zachować plik i użyć go ponownie bez pytania.

Lista kontrolna strony sprawdza do sześciu własnych plików ładowanych przez stronę główną (CSS, JavaScript i obrazy z tego samego adresu co strona) i oczekuje, że każdy będzie w pamięci podręcznej co najmniej 7 dni.

Co się liczy jako pamięć podręczna

Nagłówek pliku Wynik
Cache-Control: public, max-age=31536000, immutable OK, najlepiej dla plików z hashem w nazwie
Cache-Control: max-age=2592000 (30 dni) OK
Cache-Control: max-age=604800 (7 dni) OK, minimum
data Expires co najmniej 7 dni do przodu, bez max-age OK
Cache-Control: max-age=3600 albo brak nagłówka za krótko
Cache-Control: no-cache lub no-store brak pamięci podręcznej, niezależnie od reszty nagłówka

Plików z innych domen (Google Fonts, CDN ze skryptami, sieć reklamowa) nie sprawdzamy: nie możesz zmienić ich nagłówków. Osobna subdomena, np. static.example.com, też liczy się jako inny adres.

Jak długo jest bezpiecznie, zależy od nazwy pliku:

  • Nazwy z hashem (fingerprint), np. app-3f2a9c1d.css lub /_next/static/…, zmieniają się przy każdej zmianie treści. Zapisuj je na rok z immutable; nowa wersja to nowy plik.
  • Nazwy z wersją w parametrze, np. style.css?ver=6.6.2 (WordPress dodaje to do każdego rejestrowanego arkusza stylów i skryptu), dostają nowy adres, gdy zmienia się wersja motywu lub wtyczki. Miesiąc lub dłużej jest w porządku, o ile wersja naprawdę zmienia się razem z plikiem.
  • Zwykłe nazwy, np. /css/style.css, po edycji mają ten sam adres. Przy długim czasie powracający odwiedzający zostają ze starym plikiem. Użyj tu 7 dni i, gdy możesz, dodaj do nazwy wersję lub hash.
  • Obrazy i czcionki rzadko zmieniają się pod tą samą nazwą. Od 30 dni do roku to norma.

Sprawdź sam

Wypisz pliki ładowane przez stronę główną, a potem sprawdź nagłówki jednego z nich. Zamiast example.com i ścieżki wpisz swoje:

curl -s https://example.com | grep -oE '(href|src)="[^"]+\.(css|js|png|jpe?g|webp|svg|woff2?)[^"]*"' | head -20
curl -sI https://example.com/wp-content/themes/example/style.css | grep -iE '^(cache-control|expires):'

Naprawione oznacza, że cache-control pokazuje max-age=604800 lub więcej (albo immutable), bez no-cache ani no-store. Jeśli drugie polecenie nic nie wypisuje, plik w ogóle nie ma nagłówka pamięci podręcznej.

Jak to naprawić

Nagłówki pamięci podręcznej ustawia to, co serwuje pliki: serwer WWW, panel hostingu, CDN albo aplikacja. Wybierz to, do czego masz dostęp; wystarczy jedno miejsce.

WordPress

Sam WordPress nie wysyła nagłówków pamięci podręcznej dla plików. Robi to serwer, a niektóre wtyczki cache mogą je ustawić za Ciebie.

  • LiteSpeed Cache (na hostingu LiteSpeed): LiteSpeed Cache → Cache → Browser, włącz Browser Cache i zostaw domyślny TTL (rok). Zapisz, potem Purge All.
  • WP Rocket na Apache i LiteSpeed sam dodaje reguły pamięci podręcznej przeglądarki do .htaccess. Nie ma na to przełącznika. Na nginx nie może zapisać reguł serwera: zobacz zakładkę nginx albo zapytaj hosting.

Bez tych wtyczek dodaj reguły do .htaccess z zakładki Apache i LiteSpeed. WordPress dodaje ?ver= do rejestrowanych plików CSS i JavaScript, więc miesiąc jest dla nich bezpieczny. Jeśli edytujesz CSS motywu ręcznie, nie zmieniając wersji motywu, odwiedzający mogą widzieć stary plik tak długo, jak trwa pamięć podręczna: po takich zmianach podnieś Version: w pliku style.css motywu.

cPanel

cPanel nie ma przełącznika pamięci podręcznej przeglądarki. Reguły trafiają do pliku .htaccess w katalogu głównym strony:

  1. Otwórz Files → File Manager i przejdź do public_html (albo katalogu domeny dodatkowej).
  2. W prawym górnym rogu kliknij Settings, zaznacz Show Hidden Files (dotfiles) i zapisz.
  3. Prawy klik na .htaccess → Edit, wklej na końcu blok z zakładki Apache i LiteSpeed i zapisz.

Na hostingu LiteSpeed z WordPressem te same reguły może zapisać za Ciebie wtyczka LiteSpeed Cache (zakładka WordPress).

Plesk

W Plesku nginx zwykle stoi przed Apache i sam serwuje pliki statyczne, więc reguła należy do nginx. Przejdź do Websites & Domains → example.com → Apache & nginx Settings i w Additional nginx directives dodaj:

location ~* \.(?:css|js|mjs|png|jpe?g|gif|svg|webp|avif|ico|woff2?)$ {
    expires 30d;
}

Kliknij OK; Plesk sprawdzi składnię i przeładuje nginx.

Jeśli Plesk zgłosi zduplikowany location, definiuje go już opcja Serve static files directly by nginx. Wtedy wyłącz tę opcję i zamiast tego użyj reguł .htaccess z zakładki Apache i LiteSpeed.

nginx

Dodaj reguły w bloku server { … } strony: na Debianie i Ubuntu w /etc/nginx/sites-available/example.com, na Rocky, Alma i CentOS w /etc/nginx/conf.d/example.com.conf.

# Wynik builda z hashem w nazwie (Vite, webpack): nowa wersja to nowy plik.
location /build/ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# Wszystko inne o zwykłych nazwach.
location ~* \.(?:css|js|mjs)$ {
    expires 7d;
}
location ~* \.(?:png|jpe?g|gif|svg|webp|avif|ico|woff2?)$ {
    expires 30d;
}

expires wysyła zarówno Cache-Control: max-age=…, jak i Expires. Zamień /build/ na katalog, do którego zapisuje Twoje narzędzie do budowania.

Ostrzeżenie: add_header wewnątrz location zastępuje dla tych plików wszystkie add_header z bloku server, także nagłówki bezpieczeństwa, takie jak HSTS. Jeśli ustawiasz nagłówki w server, powtórz je też w tym location.

Przetestuj i zastosuj:

sudo nginx -t && sudo systemctl reload nginx

Apache i LiteSpeed

mod_expires ustawia zarówno Cache-Control: max-age, jak i Expires. Umieść to w .htaccess w katalogu głównym strony albo, na własnym serwerze, w wirtualnym hoście. LiteSpeed odczytuje to tak samo.

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/avif "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
</IfModule>

Jeśli Twoje pliki CSS i JavaScript mają zwykłe nazwy bez wersji, w tych dwóch liniach użyj "access plus 1 week".

Plikom z hashem w nazwie możesz dodać immutable przez mod_headers, na przykład w .htaccess wewnątrz katalogu builda:

<IfModule mod_headers.c>
    Header set Cache-Control "public, max-age=31536000, immutable"
</IfModule>

Na własnym serwerze włącz moduły i przeładuj (na Rocky, Alma i CentOS oba są domyślnie włączone; zamiast apache2 użyj httpd):

sudo a2enmod expires headers
sudo apachectl configtest && sudo systemctl reload apache2

Cloudflare

Jeśli strona działa za Cloudflare (pomarańczowa chmurka), Cloudflare może wydłużyć czas pamięci podręcznej przeglądarki dla plików, które cache'uje (domyślnie CSS, JavaScript, obrazy i czcionki):

  1. Otwórz domenę i przejdź do Caching → Configuration.
  2. W Browser Cache TTL domyślna opcja Respect Existing Headers przekazuje to, co wysyła Twój serwer. Zamiast niej wybierz wartość, np. 1 month.

Z ustawioną wartością Cloudflare używa jej, gdy serwer wysyła krótszy czas albo żaden; dłuższy max-age z Twojego serwera nadal wygrywa. Dla różnych czasów w różnych katalogach użyj Rules → Cache Rules i ustaw w regule Browser TTL.

Node.js i Next.js

Next.js w produkcji już serwuje /_next/static/… z public, max-age=31536000, immutable. Pliki w public/ dostają max-age=0, więc obrazy i czcionki stamtąd nie są zapisywane. Ustaw dla nich nagłówek w next.config.js:

module.exports = {
    async headers() {
        return [
            {
                source: '/images/:path*',
                headers: [{ key: 'Cache-Control', value: 'public, max-age=2592000' }],
            },
        ];
    },
};

Express z express.static:

// Wynik builda z hashem w nazwie: rok, immutable.
app.use('/assets', express.static('dist/assets', { maxAge: '1y', immutable: true }));

// Zwykłe nazwy: tydzień.
app.use(express.static('public', { maxAge: '7d' }));

Jeśli pliki przed aplikacją serwuje nginx, ustaw nagłówki tam (zakładka nginx).

Laravel

Vite (npm run build) zapisuje pliki z hashem w nazwie do public/build/assets, np. app-3f2a9c1d.css, a @vite je linkuje. Można je bezpiecznie zapisywać na rok. Laravel nie serwuje tych plików: robi to serwer WWW, więc nagłówek ustawia się tam.

  • nginx (Forge, Ploi, własny serwer): dodaj blok location /build/ z zakładki nginx do konfiguracji strony.
  • Apache: domyślny public/.htaccess nie ma reguł pamięci podręcznej. Dodaj blok mod_expires z zakładki Apache i LiteSpeed oraz regułę immutable w .htaccess wewnątrz public/build.

Obrazy i inne pliki umieszczone bezpośrednio w public/ zachowują swoje nazwy. 30 dni to dla nich dobra wartość.

IIS i ASP.NET

W pliku web.config strony:

<configuration>
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
    </staticContent>
  </system.webServer>
</configuration>

30.00:00:00 to 30 dni. Dla katalogu z plikami z hashem w nazwie umieść w nim web.config z 365.00:00:00. W ASP.NET Core ustaw nagłówek w UseStaticFiles przez StaticFileOptions.OnPrepareResponse.

Platformy hostowane

Shopify, Wix, Squarespace i Webflow serwują pliki motywów i obrazy z własnego CDN z własnymi nagłówkami pamięci podręcznej, zwykle z innej domeny, której lista kontrolna nie sprawdza. Jeśli oznaczony jest tam plik z Twojej domeny, kontroluje go platforma i po Twojej stronie nie ma nic do zmiany.

Po zmianie

  • Wyczyść cache CDN lub strony po zmianie nagłówków. Kopia w pamięci podręcznej zachowuje stare nagłówki, dopóki nie wygaśnie.
  • Zmiany w plikach o zwykłych nazwach pozostają niewidoczne dla powracających odwiedzających, dopóki ich pamięć podręczna nie wygaśnie. Przed dużym redesignem nadaj CSS nową nazwę lub wersję, zamiast skracać czas pamięci podręcznej.

Potwierdź poprawkę

Uruchom ponownie polecenia curl z sekcji Sprawdź sam, potem otwórz cel w PulseKeeper i kliknij Sprawdź teraz na zakładce Lista kontrolna. Pozycja zmieni się na OK w ciągu kilku minut, a nie dopiero przy kolejnym codziennym sprawdzeniu.