Wasz wybór

Powiązane artykuły

Jak zbudować stronę szybką bez CDN

Szybka strona bez CDN to cel realny — i wcale nie wymaga rozbudowanej infrastruktury ani drogich subskrypcji sieciowych. Większość problemów z czasem ładowania wynika z błędów konfiguracyjnych serwera, nieprzetworzonego kodu i brakującej warstwy cache, a nie z braku geograficznie rozproszonych węzłów. Przy dobrze ustawionym hostingu i kilku dodatkowych optymalizacjach można osiągnąć wyniki, które nie ustępują rozwiązaniom opartym na CDN — szczególnie gdy większość ruchu pochodzi z jednego regionu.

Poniżej opisujemy konkretne kroki: od doboru serwera i konfiguracji cache, przez kompresję zasobów, po ustawienia HTTP i bazy danych.

Optymalizacja hostingu jako punkt wyjścia

Hosting to fundament czasów odpowiedzi. Serwer współdzielony z dziesiątkami innych stron nigdy nie osiągnie TTFB (Time to First Byte) poniżej 200 ms przy regularnym obciążeniu — a ten wskaźnik Google traktuje jako sygnał rankingowy. Rekomendujemy przynajmniej VPS z dedykowanymi zasobami CPU i RAM, idealne są konfiguracje z dyskami NVMe zamiast tradycyjnych HDD.

Przy wyborze serwera zwracamy uwagę na kilka parametrów:

  • Lokalizacja datacenter — serwer w Warszawie będzie serwował polskich użytkowników ze średnim opóźnieniem sieciowym 5-15 ms, podczas gdy serwer w USA doda 80-120 ms wyłącznie z tytułu odległości
  • Typ dysków — NVMe to odczyt rzędu 3000-7000 MB/s wobec 500-550 MB/s w przypadku SATA SSD; przy intensywnym I/O bazy danych różnica jest odczuwalna
  • Limit połączeń do bazy danych — tani hosting często ogranicza MySQL/PostgreSQL do 25-50 jednoczesnych połączeń, co przy ruchu powyżej kilkuset użytkowników dziennie powoduje kolejkowanie zapytań
  • Wersja PHP — PHP 8.2 i 8.3 są od 20 do 40% szybsze od PHP 7.4 w testach porównawczych aplikacji opartych na WordPress czy Laravel

Warto też sprawdzić, czy dostawca umożliwia włączenie OPcache na poziomie konfiguracji serwera. To buforowanie skompilowanego kodu PHP eliminuje konieczność ponownej kompilacji skryptów przy każdym żądaniu — samo to może zredukować czas generowania strony o 30-60%.

Wybór serwera WWW — Apache, Nginx czy LiteSpeed

Nginx obsługuje połączenia w modelu asynchronicznym, co pozwala mu sprawnie zarządzać tysiącami jednoczesnych żądań przy minimalnym zużyciu pamięci. Apache z domyślną konfiguracją prefork tworzy osobny proces dla każdego połączenia — przy 200 jednoczesnych żądaniach to 200 procesów obciążających RAM. Przejście na Apache z modułem MPM Event lub wymiana na Nginx potrafi obniżyć zużycie pamięci o 40-60% i poprawić czasy odpowiedzi przy obciążeniu szczytowym.

LiteSpeed Enterprise (i jego darmowy odpowiednik OpenLiteSpeed) oferuje natywną obsługę cache bez dodatkowych wtyczek. W testach na stronach WordPress czas do pierwszego bajtu spada do 20-50 ms dla stron serwowanych z cache, co jest wynikiem porównywalnym z CDN — bez opuszczania serwera.

Cache serwera — najważniejsza warstwa przyspieszenia

Bez cache każde żądanie uruchamia pełny stos: PHP, baza danych, szablony. Przy 1000 odwiedzin dziennie to 1000 pełnych cykli generowania. Cache pozwala obsłużyć zapytanie gotowym wynikiem w 5-15 ms zamiast 300-800 ms.

Rodzaje cache i kiedy je stosować

Wyróżniamy kilka poziomów cache, które można łączyć:

Cache obiektowy (Redis lub Memcached) przechowuje wyniki zapytań do bazy danych i skompilowane fragmenty aplikacji w pamięci RAM. Redis sprawdza się lepiej w większości scenariuszy — obsługuje struktury danych, persystencję i mechanizm wygaśnięcia kluczy. Przy stronie z WordPress + WooCommerce Redis zmniejsza liczbę zapytań do MySQL o 60-80% w typowym ruchu.

Cache stron pełnych (Full Page Cache) zapisuje gotowe odpowiedzi HTML dla niezalogowanych użytkowników. To najprostszy i najskuteczniejszy rodzaj cache dla stron opartych na CMS. Narzędzia takie jak Varnish Cache działają przed serwerem WWW i serwują odpowiedź bez angażowania PHP — czas odpowiedzi spada poniżej 10 ms.

OPcache PHP buforuje skompilowany bytecode, eliminując parsowanie plików .php przy każdym żądaniu. Ustawiamy opcache.memory_consumption=256 (lub więcej przy dużych aplikacjach) i opcache.validate_timestamps=0 na środowiskach produkcyjnych, gdzie kod zmienia się rzadko.

Konfiguracja Redis jako cache obiektowego w WordPress wymaga zaledwie zainstalowania klasy object-cache.php w katalogu wp-content/ i wskazania adresu serwera Redis w wp-config.php. Efekty są widoczne natychmiast w narzędziach takich jak Query Monitor — liczba zapytań do bazy danych spada z kilkudziesięciu do kilku na podstronie.

Kompresja zasobów i optymalizacja transferu

Kompresja zmniejsza ilość danych przesyłanych między serwerem a przeglądarką. To jedna z najłatwiejszych do wdrożenia optymalizacji, a jednocześnie jedna z bardziej pomijanych w konfiguracji hostingów współdzielonych.

Gzip zmniejsza rozmiar plików tekstowych (HTML, CSS, JavaScript) o 60-80%. Brotli, nowszy algorytm obsługiwany przez wszystkie współczesne przeglądarki, osiąga kompresję o 15-25% lepszą niż Gzip przy porównywalnym czasie dekompresji po stronie klienta. W konfiguracji Nginx włączamy Brotli jako moduł (ngx_brotli) i ustawiamy Gzip jako fallback dla starszych klientów.

Minimalizacja plików CSS i JavaScript to kolejny krok. Narzędzia takie jak Terser (JS) i cssnano (CSS) usuwają białe znaki, komentarze i skracają nazwy zmiennych. Plik JavaScript o rozmiarze 450 KB po minifikacji i kompresji Brotli może zejść do 60-90 KB — to różnica kilkuset milisekund przy wolniejszych połączeniach mobilnych.

Obrazy odpowiadają zwykle za 50-70% wagi strony. WebP zastępuje JPEG i PNG przy współczynniku kompresji o 25-35% lepszym przy zbliżonej jakości wizualnej. Format AVIF idzie jeszcze dalej — redukcja o 50% względem JPEG — choć konwersja jest bardziej wymagająca obliczeniowo. Lazy loading (loading="lazy" w atrybucie img) opóźnia ładowanie obrazów poza ekranem do momentu, gdy użytkownik do nich dotrze.

Przy optymalizacji transferu warto pamiętać o ustawieniu nagłówka Cache-Control dla statycznych zasobów. Dla plików CSS, JS i obrazów z hashami w nazwach (style.a3f8c2.css) ustawiamy max-age=31536000, immutable — przeglądarka nie odpytuje serwera przez rok. To eliminuje setki żądań HTTP przy powracających użytkownikach.

Konfiguracja HTTP/2 i nagłówki odpowiedzi

HTTP/2 to zmiana protokołu, która przyspiesza komunikację bez żadnej modyfikacji kodu aplikacji. Multipleksowanie pozwala przesyłać wiele zasobów przez jedno połączenie TCP jednocześnie — w HTTP/1.1 przeglądarka otwierała 6 równoległych połączeń i kolejkowała pozostałe zasoby. HTTP/2 eliminuje ten bottleneck.

Włączenie HTTP/2 w Nginx wymaga certyfikatu SSL (HTTPS jest warunkiem obsługi protokołu w większości przeglądarek) i jednej linii konfiguracji: listen 443 ssl http2;. Certyfikat Let’s Encrypt jest bezpłatny i odnawiany automatycznie co 90 dni.

HTTP/3 z protokołem QUIC idzie jeszcze dalej — działa na UDP zamiast TCP, co eliminuje problem „head-of-line blocking” i przyspiesza nawiązywanie połączeń, szczególnie przy słabszym sygnale mobilnym. Nginx obsługuje HTTP/3 od wersji 1.25.0, choć wymaga kompilacji z biblioteką quic-nginx lub skorzystania z gotowych paczek.

Nagłówki bezpieczeństwa — Strict-Transport-Security, X-Content-Type-Options, Content-Security-Policy — to nie tylko kwestia bezpieczeństwa. Część z nich redukuje liczbę żądań inicjowanych przez przeglądarkę (HSTS eliminuje przekierowanie HTTP→HTTPS przy kolejnych wizytach) i poprawia wyniki Lighthouse w kategorii Best Practices.

Preconnect i DNS-prefetch dla zasobów zewnętrznych (czcionki Google, analityka) skracają czas nawiązania połączenia z tymi domenami. Wystarczy jeden tag w sekcji : . Jeśli czcionki hostujemy samodzielnie — co jest lepszą opcją z punktu widzenia prywatności i szybkości — całkowicie eliminujemy to zewnętrzne żądanie.

Optymalizacja bazy danych i zapytań

Baza danych to często ukryte wąskie gardło. Strony WordPress po kilku latach działania gromadzą dziesiątki tysięcy wierszy w tabelach wp_options (dane transient), wp_postmeta i wp_revisions. Regularne czyszczenie tych tabel skraca czas odpowiedzi zapytań o 30-50% przy starszych instalacjach.

Indeksy tabel są tym dla bazy danych, czym spis treści dla książki. Bez właściwego indeksu MySQL skanuje każdy wiersz tabeli przy każdym zapytaniu — przy 100 000 wierszy to zauważalne opóźnienie. Narzędzie EXPLAIN w MySQL pozwala zidentyfikować zapytania wykonujące pełny skan tabeli (type: ALL w wyniku) i dodać brakujące indeksy.

Przy aplikacjach WordPress szczególnie wartościowe są:

  • Usunięcie zbędnych rewizji wpisów — przechowywanie ostatnich 3 zamiast nieograniczonej liczby (define('WP_POST_REVISIONS', 3) w wp-config.php)
  • Wyczyszczenie tabeli wp_options z wygasłych transients — narzędzie WP-Optimize lub bezpośrednie zapytanie SQL
  • Wyłączenie autoload dla opcji niezużywanych przy każdym żądaniu (kolumna autoload = 'no' w tabeli wp_options)
  • Włączenie persistent cache dla wyników zapytań taksonomii i menu nawigacji, które rzadko się zmieniają

Konfiguracja pool’u połączeń z bazą danych też ma znaczenie. ProxySQL lub PgBouncer (dla PostgreSQL) redukują overhead nawiązywania nowego połączenia przy każdym żądaniu HTTP. W środowiskach o wysokim ruchu to różnica między TTFB 80 ms a 180 ms.

Szybka strona bez CDN to nie kwestia szczęścia ani wyjątkowo dobrego dostawcy — to wynik świadomych decyzji na każdym etapie stosu technologicznego. Serwer blisko użytkowników, Redis jako cache obiektowy, pełny page cache, Brotli, HTTP/2 i zadbana baza danych razem dają wyniki, które w Google PageSpeed Insights lądują regularnie powyżej 90 punktów. Przy ruchu krajowym to rozwiązanie kompletne — bez miesięcznych opłat za CDN i bez uzależnienia od zewnętrznych dostawców infrastruktury.

Paweł Garbacz
Paweł Garbaczhttps://parasool.pl/
Head Of SEO Paweł od lat zarządza projektami SEO, które przynoszą trwałe efekty. Strategiczne myślenie i głęboka znajomość branży pozwalają mu skutecznie prowadzić kampanie dla firm z różnych sektorów.
Popularne