Dokumentacja

Włącz Brotli lub gzip

Włącz Brotli lub gzip

HTML, CSS i JavaScript to zwykły tekst, a tekst kompresuje się bardzo dobrze: skrypt o rozmiarze 300 KB z gzipem zwykle przesyłany jest jako 70–90 KB, z Brotli jeszcze trochę mniej. Przeglądarka rozpakowuje go w ułamku milisekundy. Bez kompresji każdy odwiedzający pobiera trzy do pięciu razy więcej, niż potrzeba, co najbardziej odczuwa się na telefonie ze słabym zasięgiem, a strona traci w pomiarach szybkości Google.

Kompresja to ustawienie serwera, a nie coś, co robi kod strony. Lista kontrolna strony sprawdza ją w dwóch miejscach: na samej stronie oraz na plikach CSS i JavaScript, które strona ładuje z Twojej domeny.

Co powinno być skompresowane

Kompresuj Nie kompresuj
HTML (text/html) JPEG, PNG, WebP, AVIF, GIF
CSS (text/css) czcionki WOFF2
JavaScript (application/javascript, text/javascript) wideo, audio, ZIP, PDF
JSON, XML, SVG, zwykły tekst

Prawa kolumna jest już skompresowana; ponowna kompresja tylko zużywa procesor. Brotli (br) daje trochę mniejsze pliki niż gzip i obsługują go wszystkie obecne przeglądarki, ale do listy kontrolnej wystarczy sam gzip.

Najczęstszą przyczyną żółtej pozycji "CSS and JavaScript compressed" jest nginx: Debian i Ubuntu instalują go z gzip on, ale linia wymieniająca pozostałe typy plików jest zakomentowana, więc kompresowany jest tylko HTML.

Sprawdź sam

Zamiast example.com wpisz swoją stronę, a zamiast drugiego adresu jeden ze swoich plików CSS lub JS (lista kontrolna wymienia te, które znalazła nieskompresowane):

curl -s -o /dev/null -D - -H 'Accept-Encoding: br, gzip' https://example.com/ | grep -i '^content-encoding'
curl -s -o /dev/null -D - -H 'Accept-Encoding: br, gzip' https://example.com/assets/app.css | grep -i '^content-encoding'

content-encoding: br albo content-encoding: gzip oznacza kompresję. Brak wyniku oznacza, że plik został wysłany bez zmian.

Jak to naprawić

Wybierz miejsce, które faktycznie wysyła pliki. Jeśli przed stroną stoi Cloudflare, to on kompresuje; w przeciwnym razie jest to serwer WWW albo panel hostingu.

nginx

Otwórz /etc/nginx/nginx.conf (ta sama ścieżka na Debianie, Ubuntu, Rocky, Alma i CentOS) i w bloku http { … } upewnij się, że linie gzip są aktywne, a nie zakomentowane:

http {
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_types text/css text/plain text/xml application/javascript text/javascript
               application/json application/xml application/rss+xml image/svg+xml;
}

text/html jest kompresowany zawsze, gdy ustawiono gzip on, więc nie ma go na liście. gzip_vary mówi cache'om, że odpowiedź zależy od tego, co akceptuje przeglądarka, a gzip_proxied any utrzymuje kompresję, gdy żądanie przychodzi przez CDN albo inny proxy.

Brotli wymaga osobnego modułu ngx_brotli. Tam, gdzie dystrybucja ma go w pakiecie (w nowszych Debianie i Ubuntu jako libnginx-mod-http-brotli-filter), zainstaluj go i dodaj obok linii gzip:

brotli on;
brotli_comp_level 5;
brotli_types text/css text/plain text/xml application/javascript text/javascript
             application/json application/xml application/rss+xml image/svg+xml;

Sprawdź i zastosuj:

sudo nginx -t && sudo systemctl reload nginx

Apache i LiteSpeed

Z dostępem do serwera (Apache). Kompresja to mod_deflate. Na Debianie i Ubuntu włącz go przez sudo a2enmod deflate; na Rocky, Alma i CentOS jest ładowany domyślnie. Następnie dodaj do <VirtualHost> strony albo do .htaccess:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
    AddOutputFilterByType DEFLATE application/javascript text/javascript
    AddOutputFilterByType DEFLATE application/json application/xml application/rss+xml image/svg+xml
</IfModule>
sudo apachectl configtest && sudo systemctl reload apache2

(Na Rocky, Alma i CentOS httpd zamiast apache2.) Apache 2.4.26 i nowsze ma też mod_brotli (sudo a2enmod brotli) z filtrem BROTLI_COMPRESS dla tych samych typów.

Bez dostępu do serwera (hosting współdzielony). Wstaw ten sam blok do .htaccess w głównym folderze strony. Serwery LiteSpeed kompresują na poziomie serwera, zwykle z już włączonymi gzip i Brotli; jeśli na hostingu z LiteSpeed sprawdzenie nadal nie pokazuje kompresji, poproś wsparcie o jej włączenie.

cPanel

  1. Otwórz Software → Optimize Website.
  2. Wybierz Compress All Content (albo Compress the specified MIME types i wpisz typy z tabeli powyżej).
  3. Kliknij Update Settings.

cPanel zapisuje reguły mod_deflate w .htaccess strony. Jeśli tego ekranu nie ma albo sprawdzenie nadal nie pokazuje kompresji, serwerem może być LiteSpeed lub nginx; zapytaj hosting, dla niego to ustawienie serwera.

Plesk

W Plesku nginx zwykle stoi przed Apache i to on wysyła pliki odwiedzającemu, więc tam należy kompresja. Websites & Domains → example.com → Apache & nginx Settings, w Additional nginx directives dodaj:

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_types text/css text/plain text/xml application/javascript text/javascript
           application/json application/xml image/svg+xml;

Kliknij OK; Plesk sprawdzi składnię i przeładuje nginx. Jeśli strona działa tylko na Apache (nginx wyłączony), użyj zamiast tego bloku .htaccess z zakładki Apache.

Cloudflare

Gdy strona działa za Cloudflare (pomarańczowa chmurka), Cloudflare kompresuje HTML, CSS, JavaScript i inne typy tekstowe przez Brotli lub gzip w drodze do odwiedzającego, na każdym planie, niezależnie od tego, co robi serwer. Nie trzeba niczego włączać.

Jeśli sprawdzenie nadal nie pokazuje kompresji, poszukaj jednej z tych rzeczy:

  • Rekord jest DNS only (szara chmurka), więc ruch nie przechodzi przez Cloudflare.
  • Serwer wysyła Cache-Control: no-transform, co zabrania Cloudflare zmieniać odpowiedź.
  • Plik jest serwowany z innej domeny, która nie jest w Cloudflare.

WordPress

Sam WordPress niczego nie kompresuje; robi to serwer WWW. Wtyczki cache mogą pomóc w konfiguracji: WP Rocket zapisuje reguły mod_deflate w .htaccess, a W3 Total Cache ma opcję gzip w Performance → Browser Cache. Obie działają tylko na Apache lub LiteSpeed, gdzie .htaccess jest czytany. Na nginx te reguły nic nie robią.

Jeśli strona używa LiteSpeed Cache, kompresuje serwer LiteSpeed, a nie wtyczka. Jeśli po ustawieniu wtyczki i wyczyszczeniu cache pozycja nadal jest żółta, użyj zakładki dla swojego panelu hostingu lub serwera albo zapytaj hosting.

Node.js i Next.js

Next.js kompresuje odpowiedzi gzipem, gdy uruchamiasz go przez next start (compress: true to ustawienie domyślne). Jeśli przed nim kompresuje już nginx albo CDN, wyłącz to w next.config.js, aby praca nie była wykonywana dwa razy:

module.exports = {
    compress: false,
};

Express potrzebuje middleware compression (npm install compression), zarejestrowanego przed trasami i plikami statycznymi:

const compression = require('compression');
app.use(compression());

Przy obciążonej stronie taniej jest zostawić kompresję nginx albo CDN, a Node zostawić aplikacji.

IIS i ASP.NET

IIS domyślnie kompresuje pliki statyczne (CSS, JS), ale kompresja stron dynamicznych to osobna funkcja roli. Zainstaluj Dynamic Content Compression w Server Manager (Add Roles and Features → Web Server → Performance), a potem włącz obie w web.config strony:

<configuration>
  <system.webServer>
    <urlCompression doStaticCompression="true" doDynamicCompression="true" />
  </system.webServer>
</configuration>

Dla Brotli Microsoft udostępnia darmowe rozszerzenie IIS Compression, które dodaje schemat Brotli obok gzip.

Platformy hostowane

Shopify, Wix, Squarespace i Webflow kompresują wszystko same. Jeśli lista kontrolna zgłasza tam nieskompresowany plik, zwykle pochodzi on z aplikacji zewnętrznej albo z zewnętrznego hostingu, który możesz zapytać, a nie z platformy.

Na co uważać

  • Kopie w cache. CDN albo wtyczka cache może dalej serwować kopię zapisaną przed zmianą. Po włączeniu kompresji wyczyść cache.
  • Podwójna kompresja. zlib.output_compression w PHP i serwer WWW nie powinny kompresować jednocześnie: to marnuje procesor, a w niektórych konfiguracjach przeglądarka dostaje odpowiedź, której nie umie odczytać. Niech robi to serwer WWW.
  • Pliki skompresowane wcześniej. Narzędzia do budowania mogą tworzyć app.css.gz i app.css.br obok oryginału. nginx serwuje je przez gzip_static on; (a z modułem brotli_static on;), co oszczędza procesor przy każdym żądaniu.

Potwierdź poprawkę

Uruchom ponownie oba polecenia curl z sekcji Sprawdź sam, następnie otwórz cel w PulseKeeper i kliknij Sprawdź teraz na zakładce Lista kontrolna. Obie pozycje, dla strony oraz dla CSS i JavaScript, zmienią się na OK w ciągu kilku minut, a nie dopiero przy następnym codziennym sprawdzeniu.