# Migracja WordPressa do Astro bez utraty adresów: ten sam blog, tylko szybszy

Blog GSMX przeszedł z WordPressa na statyczne Astro i dla czytelnika zmieniła się tylko szybkość: te same adresy, wpisy, reklamy i forum obok. Pokazuję, jak to zrobiłem i sprawdziłem.

**Canonical:** https://spoko.space/pl/blog/migracja-wordpress-astro-gsmx/  
**Language:** pl  
**Published:** 2026-11-07  
**Tags:** WordPress, Astro, migracja, Cloudflare Workers, Core Web Vitals, SEO  
**Category:** Inżynieria

---
**[Blog GSMX](https://gsmx.pl/blog/) przeszedł z WordPressa na statyczne Astro i dla czytelnika zmieniła się tylko szybkość.** Adresy, wpisy i reklamy są te same, a forum obok działa jak wcześniej. Sprawdziłem 2299 starych adresów i żaden nie prowadzi w złe miejsce. Na telefonie PageSpeed Insights wzrósł z 33–85 do 99–100 (mediana z 3 przebiegów), a serwer odpowiada w niecałe 60 ms zamiast ponad sekundy.

W skrócie:

- **Ten sam adres.** Blog został pod `gsmx.pl/blog/`. Serwuje go Cloudflare Worker przypięty tylko do tej ścieżki, więc forum nie zauważyło zmiany.
- **Żaden adres nie zginął.** Wpisy zachowały slugi 1:1. Zmieniło się tylko to, co było błędem, i każda taka zmiana ma przekierowanie 301.
- **Pomiar przed i po tą samą metodą.** Te same 5 adresów, ten sam Lighthouse i mediana z 3 przebiegów. Bez tego porównanie nic nie znaczy.
- **Reklamy zostały.** To one są teraz najcięższą częścią strony, nie blog.
- **Powrót był zawsze o jedną komendę.** WordPress został na hostingu na 4 tygodnie obserwacji.

## Punkt wyjścia: WordPress obok forum {#punkt-wyjścia-wordpress-obok-forum}

gsmx.pl to przede wszystkim forum, które działa w katalogu głównym domeny. Blog z newsami GSM siedział w katalogu `/blog/`, na osobnym WordPressie, z wpisami od 2006 roku.

Stan z 25 października 2026, z produkcji i z kopii bazy:

- **26 zainstalowanych wtyczek, z czego 20 aktywnych:** Jetpack, Rank Math, Quick AdSense Reloaded, WP Hide, Fast Velocity Minify, Sucuri, Disqus Conditional Load, auto-linker SEO i inne. Do tego motyw Presso z motywem potomnym i trzy zestawy tabel w bazie po starych instalacjach.
- **33–42 skrypty i 8–10 arkuszy CSS na stronę.** HTML szedł przez Cloudflare bez cache, a serwer odpowiadał w 0,8–1,6 s.
- **Wpisy ważyły 14–17 MiB** według PageSpeed Insights. Większość tej wagi to reklamy wideo ładowane na każdym wpisie.
- **Treść z 20 lat:** kilkaset wpisów, 705 tagów, osadzenia Flash, obrazki z tinypic i fotosik, które już nie istnieją, galerie, tabele i style wpisane w HTML.

Ruch z Google był znikomy: **16 kliknięć w 16 miesięcy**. To ważne dla oceny ryzyka. Migracja nie mogła popsuć SEO, którego prawie nie było, i nie obiecuję tu wzrostu ruchu. Powody były inne. Chciałem strony bez PHP i bazy, czyli bez niczego, co trzeba łatać. Chciałem, żeby dało się ją przenieść na dowolny hosting plików. I chciałem publikować nowe wpisy z repozytorium, bez logowania do panelu.

## Najpierw pomiar „przed” {#najpierw-pomiar-przed}

Zanim cokolwiek zmieniłem, zmierzyłem produkcję. Pomiar po migracji ma sens tylko wtedy, gdy powtarzasz dokładnie to samo, więc metodę ustaliłem na początku i nie zmieniałem jej do końca:

- **5 adresów:** strona główna bloga, kategoria i trzy wpisy z lat 2026, 2010 i 2006. Stare wpisy mają najwięcej starego HTML-a.
- **Lighthouse 12 lokalnie, 3 przebiegi na adres i tryb, mediana.** Jeden przebieg kłamie. W PageSpeed Insights dwa wpisy z niemal identycznym HTML-em dostały 85 i 33.
- **PageSpeed Insights i GTmetrix** jako publiczne, sprawdzalne zrzuty.
- **Pełna lista adresów** z REST API WordPressa: wpisy, strony, kategorie, tagi, autorzy, media. Z tej listy powstał później test przekierowań.

![PageSpeed Insights dla wpisu z 2006 roku na WordPressie, telefon: wydajność 33, Total Blocking Time 7690 ms, Speed Index 21,9 s, brak danych od użytkowników](https://spoko.space/_spoko/gsmx-wordpress-psi-przed.BdhLh0iC.webp "Wpis z 2006 roku na WordPressie w PageSpeed Insights, 25 października 2026")

Jednej rzeczy nie dało się zmierzyć. Google nie miał dla bloga danych od prawdziwych użytkowników (CrUX: „Brak danych” dla wszystkich 5 adresów), bo ruch był za mały. Porównanie jest więc laboratoryjne i tak je opisuję.

## Co rozważałem i odrzuciłem {#co-rozważałem-i-odrzuciłem}

| Opcja | Dlaczego nie |
| --- | --- |
| Subdomena blog.gsmx.pl | Wymagałaby przekierowania każdego adresu z 20 lat. Ten sam adres był możliwy, więc nie było powodu go zmieniać. |
| Kopia motywu Presso w Astro | Wciągnęłaby te same biblioteki, które spowalniały WordPressa. Blog dostał nowy, prosty układ z logo i kolorami GSMX. |
| Własny CMS z panelem | Za ciężki na jednojęzyczny blog, którego autorzy są techniczni i panelu nie potrzebują. Wymaga PHP i bazy, czyli dokładnie tego, czego chciałem się pozbyć. |
| Tylko cache i sprzątanie wtyczek | Przyspieszyłoby stronę, ale PHP, baza i aktualizacje by zostały. Nie byłoby też publikacji z repozytorium. |

## Jak to działa: Worker tylko na /blog {#jak-to-działa-worker-tylko-na-blog}

Cała domena gsmx.pl przechodzi przez Cloudflare. Blog obsługuje Worker ze Static Assets, przypięty do dwóch tras: `gsmx.pl/blog` i `gsmx.pl/blog/*`. Wszystko inne trafia do serwera forum, jak przed migracją.

**Co się dzieje z żądaniem do gsmx.pl**

1. `gsmx.pl/blog` i `gsmx.pl/blog/*` (Worker bloga na Cloudflare) → cała reszta domeny (forum na PHP, bez zmian)
2. **Plik _redirects** — 1466 reguł 301 ze starych adresów, wygenerowanych przez konwerter.
3. **Gotowy plik z dist/** — Adres `/blog/slug/` to plik `dist/blog/slug/index.html`, bez uruchamiania kodu.
4. **Kod Workera, tylko gdy plik nie wystarczy** — stare adresy `?p=`; 410 dla `wp-admin`, `xmlrpc.php` i usuniętych tagów; archiwa dat, RSS, stare miniatury

- Test kontraktu URL: **2299 starych adresów, 0 niezgodnych** — 200 dla wpisu, 301 we właściwe miejsce, 410 dla usuniętego.

Trasa `gsmx.pl/blog*` wyglądałaby prościej, ale złapałaby też adresy forum, które zaczynają się od „blog”, na przykład `/blogi/`. Dlatego są dwie dokładne trasy, a test po przełączeniu sprawdzał również forum.

Astro buduje blog z `base: '/blog'` do katalogu `dist/blog/`, a Worker serwuje cały `dist/`. Adres `/blog/slug/` odpowiada wtedy plikowi `dist/blog/slug/index.html` i Cloudflare oddaje go bez uruchamiania kodu. Kod Workera działa tylko tam, gdzie plik nie wystarczy:

- **stare adresy z parametrami**, na przykład `/blog/?p=1234`, przekierowuje na właściwy wpis;
- **zwraca 410 Gone** dla `wp-admin`, `wp-login.php`, `xmlrpc.php`, `wp-json` i usuniętych tagów, żeby Google wiedział, że to celowe, a nie awaria;
- **obsługuje archiwa dat, RSS i stare ścieżki miniatur**, których nie da się opisać statyczną regułą.

Reszta przekierowań, 1466 reguł, jest w pliku `_redirects`. Generuje go konwerter, nikt nie pisze go ręcznie. Ten plik musi leżeć w katalogu głównym `dist/`, a nie w `dist/blog/`, bo tylko tam Cloudflare go czyta. W `dist/blog/` byłby zwykłym plikiem do pobrania.

Adresy bez ukośnika na końcu (`/blog/slug`) Cloudflare przekierowuje kodem 307, a nie 301 jak WordPress. Przyjąłem to świadomie: kanoniczne adresy mają ukośnik, a wersji bez niego prawie nie było w linkach ani w Search Console.

## Konwerter: treść, media i to, co zostało po 20 latach {#konwerter-treść-media-i-to-co-zostało-po-20-latach}

Konwerter czyta treść wpisów z REST API WordPressa (`content.rendered`), a resztę z lokalnej kopii bazy. Wyrenderowana treść ma już rozwinięte shortcody, galerie i akapity, czyli to, co widział czytelnik. Odtwarzanie tego z surowej treści w bazie byłoby dużym i kruchym kodem dla kilkuset wpisów. Z bazy biorę to, czego REST nie daje: meta tytuły i opisy z Rank Math, relacje i mapę mediów.

Stare wpisy zostały jako oczyszczony HTML w plikach Markdown, żeby wyglądały tak jak wcześniej. Nowe wpisy pisze się już w czystym Markdownie.

Co konwerter zrobił po drodze, według raportu migracji:

- **13 osadzeń YouTube z czasów Flasha** zamienił na lekki odtwarzacz ładowany po kliknięciu. 4 inne osadzenia Flash zamienił na notkę z linkiem.
- **Sprawdził każdy obrazek z obcego hosta.** 21 jeszcze działało, więc pobrał je na blog. 152 obrazki w 53 wpisach prowadziły do serwisów, których już nie ma (tinypic, fotosik, imageshack i stare domeny). Usunął je z treści i wypisał w raporcie.
- **Przygotował media:** 508 plików, oryginały do 1600 px i warianty WebP z `srcset`, `width` i `height`, żeby obrazki nie przesuwały tekstu.
- **Poprawił to, co było błędem:** 3 slugi z typograficznymi myślnikami i cudzysłowami zakodowanymi w adresie, podkategorie dostępne pod dwoma adresami, kategorię `bada-2`, 7 par zduplikowanych tagów (`wi-fi` i `wifi`, `app-store` i `appstore`…). Każda zmiana dostała 301, a linki wewnętrzne w treści konwerter od razu przepisał na nowe adresy.

Działające, zaindeksowane adresy zostały, nawet jeśli nie były ładne. Zmiana adresu kosztuje, a ładniejszy slug nic nie daje.

## Test kontraktu URL: 2299 adresów, 0 niezgodnych {#test-kontraktu-url-2299-adresów-0-niezgodnych}

Najtrudniejsza część migracji to nie szablony, tylko stare adresy. Dlatego z pełnej listy adresów WordPressa powstał skrypt, który dla każdego sprawdza, czy nowa strona odpowiada zgodnie z umową: 200 dla wpisu, 301 we właściwe miejsce dla zmienionego adresu, 410 dla usuniętego.

Uruchomiłem go na stagingu przed przełączeniem i na produkcji zaraz po nim:

| Źródło adresów | Adresy | Niezgodne |
| --- | --: | --: |
| Wpisy z REST API | 336 | 0 |
| Tagi z REST API | 705 | 0 |
| Stare adresy `?p=` | 707 | 0 |
| Media (ścieżki WP Hide i `wp-content`) | 300 | 0 |
| Miniatury | 194 | 0 |
| Autorzy, kategorie, strony | 33 | 0 |
| Pozostałe: RSS, archiwa dat, sitemapy, `ads.txt`, weryfikacja GSC | 24 | 0 |
| **Razem** | **2299** | **0** |

To był warunek przełączenia: 100% zgodności albo nie ma wdrożenia.

## Przełączenie bez ryzyka {#przełączenie-bez-ryzyka}

Zanim przypiąłem Workera do produkcji, sprawdziłem strefę Cloudflare. Reguły przekierowań i Page Rules działają przed Workerem, więc jedna stara reguła na `/blog` przejęłaby ruch. Rocket Loader albo zaciemnianie adresów e-mail zmieniałyby HTML. Staging był w tej samej strefie, więc porównałem jego odpowiedź z plikiem z `dist/`. Różnił się tylko skryptem Web Analytics.

Samo przełączenie to `wrangler deploy` z dwiema trasami, 2 listopada 2026 o 9:02. WordPress nie został wyłączony. Został na hostingu, tylko ruch na `/blog` przestał do niego trafiać. Powrót to usunięcie tych dwóch tras i trwa kilka sekund.

**Od planu do przełączenia**

1. **25.10: plan i pomiar „przed”** — Spec migracji, Lighthouse, PageSpeed Insights i GTmetrix na 5 adresach, pełna lista adresów.
2. **25.10: konwerter i strona w Astro** — Treść z REST API, media, mapa przekierowań, nowy układ bloga.
3. **25–27.10: Worker na stagingu** — staging.gsmx.pl, test kontraktu URL, PageSpeed Insights stagingu.
4. **30.10: kategorie i opisy** — Nowa struktura kategorii, osobne pola na nagłówek H1, tytuł SEO i opisy.
5. **2.11: przełączenie** — Trasy Workera na produkcji, test 2299 adresów, sitemapy w Search Console.
6. **2.11: pomiar „po”** — Ten sam skrypt, te same adresy, ta sama lokalizacja co 8 dni wcześniej.
7. **7.11: PageSpeed Insights i GTmetrix** — Publiczne pomiary na produkcji, trzy poprawki reklam i 3 przebiegi PageSpeed Insights.

## Wyniki: przed i po {#wyniki-przed-i-po}

Ta sama metoda co przed migracją: Lighthouse 12 lokalnie, 3 przebiegi, mediana. Strona po migracji ma reklamy AdSense, tak jak WordPress.

| Strona | Telefon | Komputer | LCP (telefon) | CLS (telefon) | Odpowiedź serwera | Żądania | Skrypty | Waga |
| --- | --: | --: | --: | --: | --: | --: | --: | --: |
| Strona główna | 36 → **94** | 80 → **100** | 11,08 → 2,21 s | 0,335 → 0,039 | 1518 → 59 ms | 83 → 28 | 36 → 5 | 2433 → 709 KB |
| Kategoria | 61 → **93** | 91 → **100** | 5,79 → 2,20 s | 0,063 → 0,039 | 1407 → 48 ms | 87 → 28 | 38 → 5 | 1315 → 717 KB |
| Wpis z 2026 | 68 → **86** | 91 → **100** | 4,93 → 1,89 s | 0,075 → 0,042 | 1059 → 46 ms | 74 → 21 | 42 → 5 | 1150 → 505 KB |
| Wpis z 2010 | 60 → **89** | 89 → **100** | 6,66 → 2,21 s | 0,136 → 0,051 | 1222 → 46 ms | 78 → 20 | 42 → 5 | 1730 → 474 KB |
| Wpis z 2006 | 49 → **87** | 89 → **100** | 6,77 → 1,74 s | 0,155 → 0,045 | 1609 → 26 ms | 73 → 20 | 42 → 5 | 1581 → 474 KB |

Najbardziej zmieniła się odpowiedź serwera. WordPress składał każdą stronę w PHP przy każdym żądaniu. Teraz Cloudflare oddaje gotowy plik z najbliższego serwera. W tym pomiarze każda z 5 stron ma na komputerze 100.

**Czas odpowiedzi serwera przed i po migracji**

| Strona | Wersja | Czas odpowiedzi |
| --- | --- | --- |
| Strona główna | WordPress, 25.10 | 1518 ms |
| Strona główna | Astro, 2.11 | 59 ms |
| Kategoria | WordPress, 25.10 | 1407 ms |
| Kategoria | Astro, 2.11 | 48 ms |
| Wpis z 2026 | WordPress, 25.10 | 1059 ms |
| Wpis z 2026 | Astro, 2.11 | 46 ms |
| Wpis z 2010 | WordPress, 25.10 | 1222 ms |
| Wpis z 2010 | Astro, 2.11 | 46 ms |
| Wpis z 2006 | WordPress, 25.10 | 1609 ms |
| Wpis z 2006 | Astro, 2.11 | 26 ms |

Mniej znaczy lepiej.

### PageSpeed Insights i GTmetrix {#pagespeed-insights-i-gtmetrix}

Lighthouse uruchamiany lokalnie łatwo podważyć, więc powtórzyłem też pomiary publiczne: PageSpeed Insights na tych samych 5 adresach, telefon i komputer, do tego GTmetrix z Seattle. Przed migracją zrobiłem w PageSpeed Insights po jednym przebiegu na adres. Po migracji zrobiłem trzy niezależne przebiegi i podaję medianę, bo jeden przebieg potrafi się różnić o kilkanaście punktów. Każdy wynik ma link do raportu.

| Strona | Telefon | Komputer | Waga (telefon) |
| --- | --: | --: | --: |
| [Strona główna](https://pagespeed.web.dev/analysis/https-gsmx-pl-blog/qawizwbss0?form_factor=mobile) | 51 → **99** | 98 → **100** | 2761 → 536 KiB |
| [Kategoria](https://pagespeed.web.dev/analysis/https-gsmx-pl-blog-kategoria-telefony/9j40n6i38j?form_factor=mobile) | 62 → **100** | 85 → **99** | 2005 → 519 KiB |
| [Wpis z 2026](https://pagespeed.web.dev/analysis/https-gsmx-pl-blog-odkryj-najlepsze-aplikacje-na-androida/2n27lenukb?form_factor=mobile) | 52 → **99** | 61 → **96** | 15 759 → 620 KiB |
| [Wpis z 2010](https://pagespeed.web.dev/analysis/https-gsmx-pl-blog-afera-prototypowa-czyli-iphone-z-san-jose/0q73umjmgf?form_factor=mobile) | 85 → **100** | 92 → **100** | 14 359 → 618 KiB |
| [Wpis z 2006](https://pagespeed.web.dev/analysis/https-gsmx-pl-blog-zdejmowanie-simlocka-ze-starszych-modeli-telefonow/prwqdy7np3?form_factor=mobile) | 33 → **99** | 62 → **99** | 16 945 → 515 KiB |

Przed migracją: 25 października 2026, jeden przebieg, Lighthouse 13.5. Po migracji: 7 listopada 2026, mediana z 3 przebiegów, Lighthouse 13.6.

We wszystkich 30 przebiegach po migracji telefon ma 97–100, a komputer 95–100. Na WordPressie było to 33–85 i 61–98. Wpis z 2006 roku miał Total Blocking Time 7690 ms, teraz ma 40–160 ms. Wpisy ważą ok. 0,5–0,6 MiB zamiast 14–17 MiB. Ułatwienia dostępu i SEO mają 100, a na WordPressie miały 79–96 i 91–92.

**PageSpeed Insights na telefonie przed i po migracji**

| Strona | Wersja | Wynik |
| --- | --- | --- |
| Strona główna | WordPress, 25.10 | 51 |
| Strona główna | Astro, 7.11 | 99 |
| Kategoria | WordPress, 25.10 | 62 |
| Kategoria | Astro, 7.11 | 100 |
| Wpis z 2026 | WordPress, 25.10 | 52 |
| Wpis z 2026 | Astro, 7.11 | 99 |
| Wpis z 2010 | WordPress, 25.10 | 85 |
| Wpis z 2010 | Astro, 7.11 | 100 |
| Wpis z 2006 | WordPress, 25.10 | 33 |
| Wpis z 2006 | Astro, 7.11 | 99 |

Więcej znaczy lepiej, maksimum to 100.

**Waga strony na telefonie przed i po migracji**

| Strona | Wersja | Waga |
| --- | --- | --- |
| Strona główna | WordPress, 25.10 | 2761 KiB |
| Strona główna | Astro, 7.11 | 536 KiB |
| Kategoria | WordPress, 25.10 | 2005 KiB |
| Kategoria | Astro, 7.11 | 519 KiB |
| Wpis z 2026 | WordPress, 25.10 | 15 759 KiB |
| Wpis z 2026 | Astro, 7.11 | 620 KiB |
| Wpis z 2010 | WordPress, 25.10 | 14 359 KiB |
| Wpis z 2010 | Astro, 7.11 | 618 KiB |
| Wpis z 2006 | WordPress, 25.10 | 16 945 KiB |
| Wpis z 2006 | Astro, 7.11 | 515 KiB |

Mniej znaczy lepiej.

### Co wykrył pierwszy pomiar {#co-wykrył-pierwszy-pomiar}

Pierwszy przebieg PageSpeed Insights po migracji nie był taki równy. Strona główna na komputerze miała 90, a dwa stare wpisy CLS 0,084 i 0,113. Lokalny Lighthouse tego nie pokazywał. Za każdym razem winne było miejsce na reklamę w treści, którego AdSense nie wypełnił. Z Polski reklama zwykle się wyświetla, a PageSpeed Insights mierzy z USA i często jej nie dostaje.

Przyczyny były trzy, a znalazłem je po kolei:

1. Puste miejsce na reklamę znikało od razu i tekst pod nim podskakiwał o ok. 300 px. Teraz znika tylko wtedy, gdy jest pod ekranem.
2. AdSense najpierw daje reklamie 280 px, a gdy jej nie ma, wyjmuje ją z układu strony. Miejsce zarezerwowane na 250 px wracało do tej wysokości i akapit pod nim podjeżdżał o 30 px. Teraz rezerwa ma 280 px.
3. Pusta reklama dostaje od AdSense szerokość 0. Wyśrodkowana przesuwała swoją zawartość o 330 px w prawo. Teraz jest wyrównana do lewej.

Po tych poprawkach CLS na komputerze wynosi najwyżej 0,011, a strona główna ma 100 we wszystkich trzech przebiegach. Wniosek ogólny: statyczna strona nie przesuwa się sama z siebie. Przesuwa ją to, co ładujesz na nią z zewnątrz, i to trzeba mierzyć z kilku miejsc, nie tylko z własnego komputera.

GTmetrix (Seattle, komputer, strona główna): ocena **C → A**, wydajność **62% → 90%**, struktura 89% → 99%, LCP 3,3 s → 0,38 s. Raporty: [przed](https://gtmetrix.com/reports/gsmx.pl/FfaUrOUo/) i [po](https://gtmetrix.com/reports/gsmx.pl/USRyZHjb/). Ten pomiar GTmetrix powstał przed poprawkami reklam.

![Wpis z 2008 roku na nowym blogu GSMX, widok na telefonie: nagłówek z logo GSMX, kategoria Rynek, tytuł „Oskarżeni o łamanie patentów! LG i Samsung w sądzie”, data, okładka i początek treści](https://spoko.space/_spoko/gsmx-astro-wpis-telefon.CWlf0rD5.webp "Wpis z 2008 roku po migracji, telefon")

## Co zostało: reklamy {#co-zostało-reklamy}

Na telefonie wynik nie dochodzi do 100 przez reklamy, nie przez blog. Na stagingu PageSpeed Insights rozpisał czas procesora na wpisie z 2026 roku:

- skrypty reklam Google: **4,2 s**;
- okno zgody na reklamy: **1,4 s**;
- JavaScript samego bloga: **41 ms**.

Gdy reklama zdąży się załadować w czasie pomiaru, wynik spada (ten wpis na stagingu: 69). Gdy nie zdąży, wynosi 99–100. Bez reklam nie da się tego poprawić, a reklamy zostają, bo zarabiają na blog.

Dwie rzeczy przy reklamach wyszły dopiero na produkcji:

- **Pierwszy pomiar „po” dał CLS 0,155–0,215 na krótkich starych wpisach.** Miejsce na reklamę w treści dostawało wysokość dopiero, gdy reklama się załadowała, i przesuwało akapit pod nią. Teraz każde miejsce rezerwuje 250 px od pierwszego renderu i CLS spadł do 0,04–0,05. Ta reszta pochodzi z okna zgody Google, nie z kodu bloga.
- **Automatyczne reklamy AdSense wstawiały się, gdzie chciały.** Wyłączyłem je dla całego `/blog/`, a blog ma 4 własne jednostki w stałych miejscach. Forum ma automatyczne reklamy jak wcześniej. Reklamy wideo, które ważyły po kilkanaście MiB na wpis, zniknęły razem z WordPressem.

## Czego nie wiem {#czego-nie-wiem}

Porównanie jest laboratoryjne. Na WordPressie Cloudflare Web Analytics zebrało przed przełączeniem tylko 4 pomiary z bloga, więc nie mam pomiaru od prawdziwych użytkowników „przed”. Nie mam też dowodu, że szybszy blog dostanie więcej ruchu z Google. Przy 16 kliknięciach w 16 miesięcy każda zmiana byłaby szumem. Okres obserwacji trwa do końca listopada, potem WordPress zostanie usunięty z hostingu.

## Po migracji: wpisy z repozytorium {#po-migracji-wpisy-z-repozytorium}

Statyczny blog nie oznacza bloga bez nowych wpisów. Wpis to plik Markdown w repozytorium. Na gsmx.pl nowe tematy zbiera automatyzacja z kanałów RSS. Ona też przygotowuje szkic ze źródłami i okładką i otwiera pull request. Przed scaleniem każdy szkic przechodzi sprawdzenie faktów ze źródłami, a potem blog buduje się i trafia na Cloudflare przez `wrangler deploy`. W pierwszym tygodniu po migracji tak ukazało się 15 wpisów. Wpis z datą w przyszłości czeka i pojawia się przy pierwszym buildzie po tej dacie.

**Droga nowego wpisu**

1. **Temat** — Automatyzacja zbiera tematy z kanałów RSS albo autor pisze wpis sam.
2. **Pull request** — Wpis jako plik Markdown, ze źródłami i okładką.
3. **Przegląd** — fakty sprawdzone ze źródłami; tekst i data publikacji
4. **Scalenie i wdrożenie** — Build Astro i `wrangler deploy` na Cloudflare.

- Opublikowany: **Wpis na gsmx.pl/blog** — Bez panelu, bazy i PHP.

## Co dalej: forum {#co-dalej-forum}

Forum na gsmx.pl nadal działa na XenForo, czyli na PHP. Testuję dla niego kilka podejść w formie POC i MVP. Ostatnio przeniosłem je testowo na Flarum. Frontend Flarum opiera się jednak na jQuery i dość starym podejściu, więc najpewniej Flarum zostanie tylko zapleczem (headless), a stronę forum przejmie Astro z Vue. Więcej o tym napiszę wkrótce.

## Kiedy taka migracja ma sens {#kiedy-taka-migracja-ma-sens}

Statyczne Astro pasuje, gdy treść zmienia się przy publikacji, a nie przy każdej wizycie. Tak jest na blogu, w serwisie newsowym i na stronie firmowej. Liczba autorów nie ma znaczenia. W WordPressie blog GSMX miał ich 17 i wszyscy zostali przeniesieni. Teraz autorem może być każdy, kto ma dostęp do repozytorium: pisze wpis jako plik Markdown w edytorze takim jak VS Code albo z pomocą asystenta AI i otwiera pull request. Na GSMX wszyscy autorzy są techniczni, więc brak panelu nikomu nie przeszkadza.

Gdy autorzy nie są techniczni i chcą zostać przy panelu, WordPress może zostać jako CMS, a Astro tylko wyświetla treść. Tak działa [polo.blue](https://polo.blue/) od 2023 roku. Oba warianty opisuję na stronie o [migracji z WordPressa do Astro](https://spoko.space/pl/migracja-wordpress-astro/).

Jeśli Twój WordPress jest wolny, a wtyczek przybywa przy każdej aktualizacji, zacznij od pomiaru i listy adresów, tak jak tutaj. To dwie rzeczy, od których zależy, czy migracja się uda. Szablony są łatwiejsze.

## Najczęściej zadawane pytania {#faq}

### Czy po migracji z WordPressa do Astro stare adresy działają? {#faq-czy-po-migracji-z-wordpressa-do-astro-stare-adresy-działają}

Tak, jeśli zadbasz o to od początku. Na gsmx.pl wszystkie wpisy zachowały adresy 1:1, a każdy adres, który się zmienił (3 slugi ze znakami zakodowanymi w URL-u, kategorie, zduplikowane tagi, ścieżki mediów), dostał przekierowanie 301. Przed przełączeniem i zaraz po nim skrypt sprawdził 2299 starych adresów. Niezgodnych było 0.

### Czy blog na Astro może działać pod /blog/ obok innej aplikacji na tej samej domenie? {#faq-czy-blog-na-astro-może-działać-pod-blog-obok-innej-aplikacji-na-tej-samej-domenie}

Tak. Na gsmx.pl główną domenę obsługuje forum na PHP, a blog serwuje Cloudflare Worker ze Static Assets przypięty do tras <code>gsmx.pl/blog</code> i <code>gsmx.pl/blog/*</code>. Reszta ruchu idzie do serwera forum jak wcześniej. Trasa <code>/blog*</code> byłaby błędem, bo złapałaby też adresy forum zaczynające się od „blog”.

### O ile szybszy jest statyczny blog od WordPressa? {#faq-o-ile-szybszy-jest-statyczny-blog-od-wordpressa}

Na tych samych 5 adresach, tym samym narzędziu i z medianą z 3 przebiegów: Lighthouse mobile wzrósł z 36–68 do 86–94, desktop z 80–91 do 100, a czas odpowiedzi serwera spadł z 0,8–1,6 s do poniżej 60 ms. W PageSpeed Insights wynik na telefonie wzrósł z 33–85 do 97–100 we wszystkich przebiegach, a GTmetrix podniósł ocenę strony głównej z C na A. Liczba żądań spadła z 73–87 do 20–28, skryptów z 36–42 do 5.

### Co z reklamami AdSense po migracji? {#faq-co-z-reklamami-adsense-po-migracji}

Zostały i to one wyznaczają teraz granicę wyniku na telefonie. Na wpisie skrypty reklam zużyły 4,2 s procesora, okno zgody 1,4 s, a JavaScript samego bloga 41 ms. Każde miejsce na reklamę rezerwuje wysokość od pierwszego renderu, bo bez tego reklama przesuwała tekst (CLS do 0,215).

### Ile trwała migracja? {#faq-ile-trwała-migracja}

Od planu do przełączenia minęło 8 dni: plan i pomiar „przed” 25 października 2026, przełączenie 2 listopada. WordPress został na hostingu na 4 tygodnie obserwacji, więc powrót to usunięcie dwóch tras Workera.

### Jak publikuje się wpisy, skoro nie ma panelu? {#faq-jak-publikuje-się-wpisy-skoro-nie-ma-panelu}

Wpis to plik Markdown w repozytorium. Na gsmx.pl nowe tematy zbiera automatyzacja z kanałów RSS, ona też przygotowuje szkic i otwiera z nim pull request, a po przeglądzie i scaleniu blog buduje się i trafia na Cloudflare przez <code>wrangler deploy</code>. W pierwszym tygodniu po migracji tak powstało 15 wpisów.


## Źródła {#sources}

- [Cloudflare Workers: Static Assets](https://developers.cloudflare.com/workers/static-assets/) — Serwowanie plików statycznych przez Workera, w tym run_worker_first.
- [Cloudflare Workers: przekierowania w Static Assets](https://developers.cloudflare.com/workers/static-assets/redirects/) — Format i zasady pliku _redirects.
- [Cloudflare Workers: HTML handling](https://developers.cloudflare.com/workers/static-assets/routing/advanced/html-handling/) — Tryb auto-trailing-slash i przekierowanie adresów bez ukośnika na końcu.
- [Cloudflare Workers: Routes](https://developers.cloudflare.com/workers/configuration/routing/routes/) — Przypinanie Workera do ścieżek w strefie, w której działa inna aplikacja.
- [Astro: opcje konfiguracji](https://docs.astro.build/en/reference/configuration-reference/) — base, trailingSlash, build.format i outDir użyte do zbudowania bloga pod /blog/.
- [WordPress REST API](https://developer.wordpress.org/rest-api/) — Źródło wyrenderowanej treści wpisów (content.rendered) dla konwertera.
- [Pagefind](https://pagefind.app/) — Statyczna wyszukiwarka, która zastąpiła wyszukiwanie WordPressa.
- [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview) — Narzędzie użyte do pomiarów przed i po (mediana z 3 przebiegów).
- [GTmetrix: gsmx.pl/blog przed migracją (25.10.2026)](https://gtmetrix.com/reports/gsmx.pl/FfaUrOUo/) — WordPress, Seattle, komputer: ocena C, wydajność 62%.
- [GTmetrix: gsmx.pl/blog po migracji (7.11.2026)](https://gtmetrix.com/reports/gsmx.pl/USRyZHjb/) — Astro, Seattle, komputer: ocena A, wydajność 90%.
