- Jak działa Gzip i kiedy go używać
- Co faktycznie kompresujemy
- Co kompresować, a czego nie
- Gzip a Brotli
- Wymagania wstępne
- Włączanie Gzip na Apache
- Sprawdź moduł mod_deflate i mod_filter
- Konfiguracja globalna (apache2.conf lub vhost)
- Konfiguracja w .htaccess (hostingi współdzielone)
- Wykluczenia i ochrona przed podwójną kompresją
- Cache i nagłówek Vary
- Test i przeładowanie
- Włączanie Gzip na Nginx
- Podstawowe włączenie w bloku http
- Kompresja dynamiczna i statyczna
- HTTP/2, TLS i bezpieczeństwo
- Przeładowanie i walidacja
- IIS, PHP, Node.js i rozwiązania CDN
- IIS: włączanie kompresji w Managerze
- PHP: zlib.output_compression lub ob_gzhandler
- Node.js: middleware compression
- CDN i reverse proxy (Cloudflare, CloudFront, Fastly)
- WordPress i inne CMS
- Weryfikacja i rozwiązywanie problemów
- Szybkie testy w terminalu
- DevTools i Lighthouse
- Typowe konflikty i ich naprawa
- Bezpieczeństwo: kiedy rozważyć wyłączenie
- Monitorowanie i metryki
- Najlepsze praktyki wdrożeniowe
- Lista kontrolna
- Dobór Gzip vs Brotli
- Integracja z pipeline i CI/CD
- Specjalne przypadki i kompatybilność
- Szybkie instrukcje do skopiowania
Przyspieszenie ładowania witryny zaczyna się od zmniejszenia liczby bajtów wysyłanych do przeglądarki. Najprostszym krokiem jest włączenie Gzip, czyli bezstratnej kompresja transferu HTTP. W tym praktycznym przewodniku przeprowadzę Cię przez konfigurację na różnych platformach, pokażę testy, typowe błędy i bezpieczne ustawienia. Zadbamy też o prawidłowe nagłówki, współpracę z cache i to, by Twój serwer zyskał realną wydajność bez efektów ubocznych. Omówimy Apache, .htaccess, Nginx oraz alternatywy jak Brotli.
Jak działa Gzip i kiedy go używać
Co faktycznie kompresujemy
Gzip zmniejsza rozmiar treści tekstowych przed wysłaniem do przeglądarki. W praktyce największe zyski widać na plikach HTML, CSS, JavaScript, JSON, SVG, XML i czystym tekście. Kompresja działa w locie (dynamicznie) lub na gotowych, wcześniej spakowanych plikach (statycznie). Po stronie klienta przeglądarka informuje o obsługiwanych algorytmach w nagłówku Accept-Encoding, a serwer wybiera najlepszy wariant i odsyła Content-Encoding: gzip.
Co kompresować, a czego nie
- Kompresuj: text/html, text/css, application/javascript, application/json, image/svg+xml, application/xml, text/plain, font/woff2 (zwykle już skompresowany – niektóre serwery i tak go nie dotykają).
- Nie kompresuj: JPEG, PNG, WebP, AVIF, MP4, PDF, WOFF2 – te formaty mają już własną, skuteczną kompresję; dodatkowe gzipowanie tylko doda narzut CPU i nie zmniejszy plików.
- Ostrożnie kompresuj odpowiedzi bardzo małe (poniżej ~1 kB) – narzut nagłówków i inicjalizacji potrafi zjeść korzyści.
Gzip a Brotli
Brotli bywa skuteczniejszy (mniejsze pliki) i jest szeroko wspierany, lecz jego kompresja bywa cięższa CPU-owo. W praktyce stosuje się strategię: Brotli dla HTTPS i nowoczesnych przeglądarek, Gzip jako bezpieczny fallback. Jeśli nie możesz wdrożyć Brotli, samo Gzip zapewnia duży zysk i bardzo dobrą kompatybilność.
Wymagania wstępne
- Dostęp do konfiguracji serwera www lub przynajmniej możliwość edycji pliku .htaccess na hostingu współdzielonym.
- Możliwość przeładowania/ponownego uruchomienia usługi (service reload, panel hostingowy lub SSH).
- Dostęp do narzędzi testowych: curl, przeglądarka z DevTools, ewentualnie Lighthouse.
Włączanie Gzip na Apache
Sprawdź moduł mod_deflate i mod_filter
- Na serwerze z SSH: a2enmod deflate filter, a potem przeładuj usługę: systemctl reload apache2 (Debian/Ubuntu) lub odpowiednik dla Twojej dystrybucji.
- Jeśli nie masz dostępu do globalnej konfiguracji, skorzystasz z pliku .htaccess — pamiętaj, że hosting musi zezwalać na AllowOverride.
Konfiguracja globalna (apache2.conf lub vhost)
Wstaw do sekcji serwera (np. w pliku vhost):
- AddOutputFilterByType DEFLATE text/html text/plain text/css application/javascript application/json application/xml image/svg+xml
- DeflateCompressionLevel 6
- BrowserMatch ^Mozilla/4 gzip-only-text/html
- Header append Vary Accept-Encoding
- Header set Content-Encoding gzip env=compressible
Uwaga: niektóre dystrybucje używają modułu headers do ustawiania nagłówków. Upewnij się, że jest aktywny (a2enmod headers). DeflateCompressionLevel pozwala zmienić balans CPU/rozmiar (4–7 to rozsądny kompromis).
Konfiguracja w .htaccess (hostingi współdzielone)
Dodaj do .htaccess w katalogu głównym witryny:
- IfModule mod_deflate.c
- AddOutputFilterByType DEFLATE text/html text/plain text/css application/javascript application/json application/xml image/svg+xml
- DeflateCompressionLevel 6
- SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|webp|avif|mp4|pdf|woff2)$ no-gzip dont-vary
- Header append Vary Accept-Encoding env=!dont-vary
- /IfModule
Składnię IfModule/IfModule domknij odpowiednimi nawiasami (ukośniki wskazują miejsce zamknięcia w przykładzie). Reguła SetEnvIfNoCase pozwala wykluczyć typy, których nie chcesz kompresować.
Wykluczenia i ochrona przed podwójną kompresją
- Jeśli aplikacja sama kompresuje odpowiedzi (np. PHP z zlib.output_compression), nie włączaj tego równocześnie w serwerze — grozi uszkodzeniem danych lub błędami w kliencie.
- Nie kompresuj odpowiedzi już podpisanych Content-Encoding. W Apache można warunkować Header set Content-Encoding gzip env=compressible tak, by ustawiać go tylko dla wskazanych typów.
Cache i nagłówek Vary
Koniecznie ustaw Vary: Accept-Encoding. Dzięki temu cache pośrednie (CDN, proxy) przechowują osobne kopie skompresowaną i nieskompresowaną. Przykład w .htaccess: Header append Vary Accept-Encoding.
Test i przeładowanie
- Przeładuj Apache: systemctl reload apache2 lub apachectl graceful.
- Sprawdź curl: curl -I -H „Accept-Encoding: gzip” https://twojadomena.pl/ i upewnij się, że widzisz Content-Encoding: gzip oraz Vary: Accept-Encoding.
Włączanie Gzip na Nginx
Podstawowe włączenie w bloku http
Edytuj /etc/nginx/nginx.conf lub plik w /etc/nginx/conf.d/ i w sekcji http dodaj:
- gzip on;
- gzip_comp_level 5;
- gzip_min_length 1024;
- gzip_proxied any;
- gzip_vary on;
- gzip_types text/plain text/css application/javascript application/json application/xml image/svg+xml;
gzip_comp_level 4–6 zapewnia dobry kompromis. gzip_min_length chroni przed kompresją bardzo małych odpowiedzi. gzip_vary dodaje Vary: Accept-Encoding.
Kompresja dynamiczna i statyczna
- Dynamiczna: jak wyżej — Nginx kompresuje odpowiedź w locie.
- Statyczna: jeśli utrzymujesz zasoby w wersjach .gz, włącz gzip_static on; i serwuj pliki prekompresowane (np. style.css.gz). To zdejmuje obciążenie CPU z serwera i bywa korzystne przy dużym ruchu.
- Automatyczne budowanie .gz: zorganizuj pipeline (np. npm scripts, Gulp, Webpack) generujący .gz w czasie deployu.
HTTP/2, TLS i bezpieczeństwo
Kompresuj tak samo dla HTTP/2; mechanizmy HPACK/H2 nie zastępują kompresji treści. Unikaj kompresji odpowiedzi wrażliwych z danymi tajnymi, zwłaszcza gdy treść zawiera elementy kontrolowane przez użytkownika i jest łączona z danymi poufnymi (ryzyko wektorów jak BREACH). Rozważ wyłączenie kompresji dla ścieżek z tokenami CSRF lub parametrami tajnymi.
Przeładowanie i walidacja
- Sprawdź składnię: nginx -t.
- Przeładuj: systemctl reload nginx.
- Test: curl -I -H „Accept-Encoding: gzip” https://twojadomena.pl/ i upewnij się, że widzisz Content-Encoding: gzip i Vary: Accept-Encoding.
IIS, PHP, Node.js i rozwiązania CDN
IIS: włączanie kompresji w Managerze
- Otwórz IIS Manager → Compression.
- Włącz Enable dynamic content compression oraz Enable static content compression.
- W razie potrzeby dodaj/zmodyfikuj typy MIME w applicationHost.config (section system.webServer/httpCompression i urlCompression).
- Recykl aplikacji lub iisreset, następnie testuj nagłówki.
PHP: zlib.output_compression lub ob_gzhandler
- php.ini: zlib.output_compression=On oraz zlib.output_compression_level=5–6. Zrestartuj FPM/Apache.
- Lub w kodzie: ob_start(’ob_gzhandler’); przed wysłaniem danych. Pamiętaj, by nie dublować z kompresją w serwerze www.
- Jeśli używasz frameworków, sprawdź czy nie mają własnej warstwy kompresji middleware.
Node.js: middleware compression
- Dodaj pakiet: npm i compression.
- W aplikacji Express: const compression = require(’compression’); app.use(compression({ level: 6, threshold: '1kb’ }));
- Wyklucz już skompresowane typy (np. obrazy), ustaw Vary: Accept-Encoding. W przypadku SSR zwróć uwagę na fragmenty wrażliwe na BREACH.
CDN i reverse proxy (Cloudflare, CloudFront, Fastly)
- Cloudflare: włącz Auto Minify i Brotli/Gzip w sekcji Speed → Optimization. Dla starszych klientów CDN dostarczy Gzip, dla nowoczesnych Brotli.
- Amazon CloudFront: w atrybutach Behavior → Compress objects automatically ustaw On, dodaj typy MIME.
- Fastly/akamai: w politykach włącz kompresję i potwierdź dodanie Vary: Accept-Encoding.
- Upewnij się, że origin nie podwaja kompresji; często najlepiej pozwolić CDN-owi kompresować na krawędzi, a origin serwować bez Content-Encoding.
WordPress i inne CMS
- Jeśli nie masz dostępu do serwera, użyj wtyczek optimize/performace (np. włączających kompresję i dodających nagłówek Vary).
- Na hostingach współdzielonych kompresję często włącza panel. Sprawdź dokumentację dostawcy.
- Niektóre wtyczki minifikujące mają własną opcję Gzip — nie duplikuj z konfiguracją serwera.
Weryfikacja i rozwiązywanie problemów
Szybkie testy w terminalu
- curl -I -H „Accept-Encoding: gzip” https://twojadomena.pl/ — sprawdź Content-Encoding: gzip i Vary: Accept-Encoding.
- curl -s -H „Accept-Encoding: gzip” https://twojadomena.pl/ | wc -c vs. curl -s https://twojadomena.pl/ | wc -c — porównaj rozmiary strumienia.
- Jeśli serwujesz gzip_static, spróbuj pobrać konkretny zasób CSS/JS i zobacz, czy rozmiar maleje.
DevTools i Lighthouse
- W Chrome → DevTools → Network → wybierz zasób → zakładka Headers: sprawdź Content-Encoding i size (zobacz transferred vs resource size).
- Lighthouse/Pagespeed: reguła Enable text compression pokaże, które zasoby nie są kompresowane i ile możesz zyskać.
Typowe konflikty i ich naprawa
- Podwójna kompresja: usuń nakładające się warstwy (np. PHP zlib i Nginx jednocześnie). Ustal, gdzie kompresujesz: aplikacja, serwer, czy CDN.
- Błędne typy MIME: jeśli Content-Type jest application/octet-stream, reguły oparte na typach mogą nie zadziałać. Ustaw właściwe typy MIME.
- Proxies i stare przeglądarki: w razie problemów pozostaw Vary: Accept-Encoding i nie wymuszaj kompresji na user-agentach, które jej nie obsługują.
- Uszkodzone odpowiedzi: sprawdź, czy żaden filtr nie modyfikuje Content-Length po kompresji; najlepiej go nie ustawiać ręcznie przy dynamicznych odpowiedziach.
Bezpieczeństwo: kiedy rozważyć wyłączenie
- BREACH/CRIME: jeśli odpowiedź łączy dane tajne (np. tokeny) z danymi kontrolowanymi przez użytkownika i jest kompresowana, rozważ wyłączenie kompresji dla takich endpointów lub wstrzykiwanie losowego paddowania.
- API z danymi poufnymi: zostaw Gzip, ale ogranicz do application/json bez pól z tajnymi tokenami w odpowiedzi, lub wyłącz dla specyficznych tras.
Monitorowanie i metryki
- Zbieraj rozmiary transferu i CPU na warstwie serwera/CDN. Upewnij się, że poziom kompresji nie przeciąża procesora w godzinach szczytu.
- Sprawdzaj procent hitów cache. Przy prawidłowym Vary: Accept-Encoding nie powinno dochodzić do błędnych trafień.
Najlepsze praktyki wdrożeniowe
Lista kontrolna
- Włącz kompresję dla typów tekstowych; wyklucz formaty już skompresowane (JPEG/PNG/WebP/AVIF/WOFF2/MP4/PDF).
- Ustaw Vary: Accept-Encoding i poprawne Content-Type dla każdego zasobu.
- Zadbaj o minimalny rozmiar (Nginx: gzip_min_length, Apache: rozważ reguły warunkowe) oraz rozsądny poziom (5–6).
- Sprawdź brak podwójnej kompresji na styku aplikacja–serwer–CDN.
- Rozważ gzip_static lub prekompresję w pipeline, jeśli masz wysokie RPS i ciężkie pliki JS/CSS.
- Przetestuj w curl i DevTools, a następnie w Lighthouse.
Dobór Gzip vs Brotli
- Jeśli możesz, włącz oba: Brotli dla HTTPS/nowoczesnych klientów, Gzip jako fallback.
- Dla serwerów o słabszym CPU trzymaj umiarkowane poziomy kompresji; ciężkie poziomy Brotli (9–11) stosuj tylko przy prekompresji statycznej.
Integracja z pipeline i CI/CD
- Buduj .gz (i .br) dla plików statycznych podczas deployu; publikuj obok oryginałów i ustaw serwer/CDN do serwowania właściwego wariantu.
- Automatyczne testy: skrypt CI może wywołać curl i sprawdzić Content-Encoding dla kilku kluczowych zasobów.
Specjalne przypadki i kompatybilność
- Aplikacje SPA: duży bundle JS przynosi największe zyski z kompresji; rozważ dzielenie kodu i prekompresję.
- Serwowanie fontów: WOFF2 jest skompresowany; unikaj dodatkowego Gzip, ale zostaw nagłówek Vary.
- Edge computing/Workers: kompresuj na krawędzi, a origin zostaw odciążony.
Szybkie instrukcje do skopiowania
- Apache (.htaccess): AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json image/svg+xml; Header append Vary Accept-Encoding; DeflateCompressionLevel 6.
- Nginx (http): gzip on; gzip_types text/html text/css application/javascript application/json image/svg+xml; gzip_comp_level 5; gzip_min_length 1024; gzip_vary on.
- Node (Express): app.use(require(’compression’)({ level: 6, threshold: '1kb’ }));
- PHP (php.ini): zlib.output_compression=On; zlib.output_compression_level=6.