Architektura wysp jako warstwa, nie framework
Najpierw trzeba przestawić sobie jedną rzecz w głowie: Astro nie jest konkurentem dla React, Vue czy Svelte i niczego nie zastępuje. To warstwa architektoniczna, która decyduje, jak i kiedy kod tych frameworków trafia do klienta.
Astro renderuje stronę domyślnie jako HTML i CSS, zerując client-side JavaScript. Tam, gdzie potrzebujesz interaktywności, umieszczasz — komponent konkretnego frameworka, który niezależnie. Ponieważ wyspy są od siebie odseparowane, możesz mieszać kilka frameworków na jednej stronie: React obsługuje wyszukiwarkę, Vue zasila widżet onboardingu, Svelte renderuje lekki licznik. Każda wyspa płaci tylko za swój własny JavaScript.
To właśnie ta niezależność czyni Astro idealnym narzędziem do migracji: pozwala inkrementalnie konwertować istniejącą witrynę na inny framework bez downtime’u.
Kiedy Astro ma sens jako warstwa migracyjna
Astro nie naprawia każdej starszej aplikacji frontendowej, działa najlepiej wtedy, gdy publiczna część systemu jest w dużej mierze treściowa, ale w środku ma kilka ciężkich, interaktywnych fragmentów. Może to być strona landingowa,wyszukiwarka, konfigurator, kalkulator, panel porównania, mapa, formularz wieloetapowy albo widget użytkownika.
W takim projekcie nie musisz przenosić całego frontendu do jednego nowego frameworka. Możesz potraktować Astro jako warstwę kompozycji: statyczne sekcje lądują w .astro, stary React działa jako wyspa, nowy moduł powstaje w Svelte, a istniejący komponent Vue zostaje tam, gdzie już spełnia swoje zadanie.
To podejście ma sens szczególnie wtedy, gdy:
- część strony musi zostać stabilna, bo obsługuje sprzedaż, leady albo ruch SEO,
- zespół nie ma budżetu na jednorazowe przepisanie całego systemu,
- kilka modułów pochodzi z różnych epok technologicznych,
- nowy kod chcesz pisać inaczej, ale bez zatrzymywania starego,
- największy koszt wydajnościowy siedzi w kilku konkretnych panelach, nie w całym systemie.
Jeśli jednak cały produkt jest jedną aplikacją z intensywnym stanem, sesją użytkownika, panelem administracyjnym, routingiem aplikacyjnym i zależnościami między ekranami, Astro może być złym narzędziem na rdzeń. Wtedy lepiej rozważyć jeden framework aplikacyjny, a Astro zostawić dla marketingu, dokumentacji albo bloga.
Audyt legacy przed migracją
Najczęstszy błąd to zacząć od pytania „React, Vue czy Svelte?”. W starszej architekturze ważniejsze jest pytanie: które fragmenty systemu można bezpiecznie odizolować?
Przed pierwszą migracją rozpisz moduły w prostej tabeli:
| Moduł | Obecny framework | Stan | Routing | CSS | Ryzyko | Decyzja |
|---|---|---|---|---|---|---|
| Hero i sekcje ofertowe | React | brak | brak | globalny CSS | niskie | przenieść do .astro |
| Wyszukiwarka produktów | React | lokalny stan + API | query params | CSS Modules | średnie | wyspa React, potem refaktor |
| Konfigurator ceny | Vue | dużo stanu | brak | scoped styles | wysokie | zostawić jako wyspę |
| Nowy kalkulator ROI | brak | lokalny stan | brak | nowy design system | niskie | zbudować w Svelte |
To ćwiczenie wymusza decyzje techniczne bez zgadywania. Moduł statyczny nie powinien dalej żyć w Reactcie tylko dlatego, że tak powstał pięć lat temu. Moduł krytyczny, który działa i ma wiele edge case’ów, nie musi być przepisywany pierwszy tylko dlatego, że wygląda „staro”.
W praktyce szukasz trzech typów fragmentów:
- statyczne — treść, layout, sekcje marketingowe, FAQ, tabele, opisy; najlepszy kandydat do
.astro, - izolowane interakcje — formularz, filtr, kalkulator, galeria; dobry kandydat na wyspę,
- aplikacyjne moduły — dashboard, edytor, koszyk, panel użytkownika; zostaw ostrożnie albo trzymaj poza Astro, jeśli zależności są zbyt silne.
Konfiguracja: trzy frameworki obok siebie
Technicznie to zaskakująco proste. Instalujesz oficjalne integracje i deklarujesz je w konfiguracji:
Astro oficjalnie wspiera React, Preact, Svelte, Vue, SolidJS i AlpineJS, a społeczność dorzuca kolejne (Angular, Qwik). Komponenty trzymasz po prostu w odpowiednich rozszerzeniach, czyli .jsx/.tsx dla Reacta, .vue dla Vue, .svelte dla Svelte, a potem je importujesz do strony Astro:
Jedna ważna granica: plik komponentu danego frameworka nie może mieszać frameworków w środku. Nie wstawisz Vue do wnętrza komponentu React. Mieszanie odbywa się na poziomie strony Astro, która jest rodzicem renderującym wyspy. To pozwala budować całe „aplikacje” w wybranym frameworku i osadzać je przez komponent-rodzic.
Dyrektywy client: — kontrola kosztu hydratacji
Sekret wydajnej migracji leży w dyrektywach hydratacji. To one decydują, kiedy dana wyspa pobiera i uruchamia swój JavaScript:
client:load— hydratacja natychmiast po załadowaniu strony. Dla elementów krytycznych, widocznych od razu.client:idle— gdy przeglądarka skończy pilniejsze zadania. Dla elementów ważnych, ale nie pilnych.client:visible— dopiero gdy element wejdzie w viewport. Idealne dla ciężkich, starych paneli niżej na stronie — nie płacisz za ich JS, dopóki użytkownik do nich nie dotrze.client:only— pomija render po stronie serwera; wyspa istnieje wyłącznie w kliencie (musisz podać framework, np.client:only="react").
W migracji legacy client:visible pozwala zostawić stary, ciężki panel React na stronie, ale odłożyć jego hydratację do momentu, w którym użytkownik faktycznie do niego dociera. Dzięki temu reszta strony może załadować się szybciej, bez płacenia kosztu JavaScriptu za moduł, którego jeszcze nie widać.
Wielka migracja nie wymaga wielkiego ryzyka. Wymaga architektury, która pozwala wymieniać panele po jednym, podczas gdy produkcja dalej zarabia.
Strategia migracji: jak odciążać stare panele
Teraz złóżmy to w plan działania, który nie przerywa dostaw na produkcję.
Krok 1: opakuj istniejącą aplikację jako wyspę
Zamiast przepisywać, najpierw przenieś istniejący panel (np. cały moduł React) do Astro jako pojedynczą wyspę client:only="react". Strona ładuje się jak dotąd, ale od teraz żyje w środowisku Astro. Zero zmian w logice, zero downtime’u. To Twój bezpieczny punkt wyjścia.
W realnym projekcie „opakowanie” rzadko oznacza samo przeniesienie pliku. Często musisz odtworzyć minimalny zestaw zależności starego modułu:
- providery Reacta, Vue pluginy albo Svelte store’y,
- klienta API i konfigurację środowisk,
- globalne style, reset CSS albo style biblioteki komponentów,
- tłumaczenia i formatowanie dat/liczb,
- analitykę zdarzeń, jeśli moduł wysyła eventy do GA4, Segmenta albo własnego backendu,
- placeholder, jeśli używasz
client:onlyi komponent nie renderuje HTML na serwerze.
Dobrym wzorcem jest cienki adapter:
Adapter jest miejscem, w którym zamykasz brzydkie zależności starego świata. Reszta strony Astro nie musi wiedzieć, jak działa dawny moduł.
Krok 2: wyrwij statyczne fragmenty do HTML-a
Wiele „aplikacji” legacy renderuje przez ciężki framework rzeczy, które są w istocie statyczne: nagłówki, opisy, sekcje marketingowe. Przenieś je do natywnego Astro (czysty HTML). Każdy taki fragment to JavaScript, którego już nie wysyłasz — strona przyspiesza, a Ty nie dotknąłeś krytycznej logiki.
To zwykle najtańszy zysk. Sekcja hero, lista benefitów, porównanie pakietów, statyczne FAQ albo bloki case study nie potrzebują stanu frameworka. W Astro mogą zostać zwykłym HTML-em, komponentem .astro albo treścią z MDX/CMS. Jeśli wcześniej żyły w Reactcie tylko dlatego, że cały projekt był Reactowy, migracja usuwa koszt bez zmiany logiki biznesowej.
Krok 3: wymieniaj panele po jednym, w nowym frameworku
Tu wkracza wieloframeworkowość. Nowe lub przebudowywane panele możesz pisać w lżejszym frameworku (np. Svelte, który kompiluje się do szczupłego, beznarzutowego JavaScriptu i wyjątkowo dobrze współgra z filozofią Astro), podczas gdy stare panele wciąż działają w Reactcie obok. Wymieniasz je pojedynczo, wyspa po wyspie, każdy za osobnym, bezpiecznym deployem. Produkcja nigdy nie stoi.
Nie traktuj tego jako zachęty do technologicznego chaosu. Nowy framework powinien mieć uzasadnienie: mniejszy koszt runtime, kompetencje zespołu, lepsza biblioteka do konkretnego widgetu albo plan stopniowego wygaszania starego Reacta/Vue. Jeśli każdy nowy komponent powstaje w innym frameworku „bo można”, Astro nie rozwiązuje długu technicznego — tylko go estetycznie opakowuje.
Krok 4: domknij migrację, gdy to ma sens
Nie ma przymusu, by skończyć „na 100%”. Jeśli stary panel działa stabilnie i rzadko się zmienia, może spokojnie zostać w Reactcie jako wyspa client:visible. Migrujesz to, co aktywnie rozwijasz i co realnie obciąża wydajność — resztę zostawiasz w spokoju. To racjonalne zarządzanie długiem, nie dogmatyczne przepisywanie.
Komunikacja między wyspami
Wyspy Astro są niezależne i to spora zalet pod kątem wydajności, ale z drugiej strony ograniczenie dla architektury. Reactowy komponent nie dzieli automatycznie stanu z komponentem Vue, a Svelte store nie jest widoczny w starym panelu Reacta.
Masz więc trzy opcje.
1. Props z rodzica Astro. Najprostsze rozwiązanie dla danych początkowych: locale, feature flag, początkowy filtr, identyfikator produktu, wariant A/B.
2. URL jako wspólny kontrakt. Dobre dla filtrów, paginacji i stanów, które mają być linkowalne. React może zapisać ?q=astro&sort=price, a Svelte lub Vue może odczytać ten sam parametr po wejściu użytkownika w kolejną sekcję.
3. Zdarzenia DOM albo mały store cross-framework. Jeśli wyspy muszą zareagować na siebie na tej samej stronie, użyj jawnego kontraktu:
Jeśli takich połączeń robi się dużo, to sygnał ostrzegawczy. Jedna lub dwie jawne integracje między wyspami są normalne. Gęsta siatka eventów oznacza, że prawdopodobnie budujesz aplikację z dużym współdzielonym stanem i powinieneś wrócić do jednego frameworka aplikacyjnego.
Budżet JavaScriptu i pomiar efektu
Migracja legacy ma sens tylko wtedy, gdy poprawia realny stan projektu: mniej JavaScriptu, szybsze wejście w interakcję, prostsze wdrożenia albo mniejszy koszt utrzymania. Dlatego przed migracją zapisz stan wyjściowy: rozmiar JS dla trasy, liczbę hydratowanych wysp oraz LCP, INP i TBT z Lighthouse albo WebPageTest. Do tego zbierz błędy z konsoli i Sentry, najcięższe zależności z bundle analyzera oraz krytyczne eventy biznesowe, jak wysłanie formularza czy kliknięcie CTA.
Po każdym etapie porównujesz wynik. Jeśli wyciągnięcie statycznych sekcji do .astro obniżyło JS o 80 KB, to masz twardy argument za kontynuacją. Jeśli przeniesienie jednego widgetu do Svelte dołożyło dodatkowy runtime na stronie, która i tak ma Reacta, decyzja może być gorsza niż wyglądała w pull requeście.
Praktyczna zasada: nie mieszaj frameworków bez budżetu. Dopuszczalne jest przejściowe posiadanie Reacta i Vue na jednej stronie, jeśli to etap migracji. Nie jest dopuszczalne dokładanie trzeciego runtime’u bez jasnego powodu i pomiaru kosztu.
Rollout, testy i rollback
Migracja legacy powinna iść mniejszymi deployami niż zwykły feature. Każdy krok zmienia nie tylko kod, ale też sposób ładowania, hydratacji i komunikacji z przeglądarką.
Minimalny plan wdrożenia wygląda tak:
- Wybierz moduł o niskim lub średnim ryzyku, ale mierzalnym koszcie.
- Owiń go adapterem i uruchom jako wyspę bez zmiany logiki.
- Dodaj test E2E dla głównego scenariusza użytkownika.
- Zmierz bundle, Lighthouse i błędy runtime przed/po.
- Włącz feature flagę, jeśli moduł obsługuje krytyczną ścieżkę.
- Wdróż na małym zakresie, obserwuj błędy i eventy konwersji.
- Dopiero potem wyciągaj statykę albo przepisuj kolejny panel.
Rollback też musi być prosty. Jeśli nowa wyspa psuje formularz lub tracking, wracasz do starego komponentu przez flagę albo szybki revert pojedynczego modułu. To właśnie różni migrację inkrementalną od pełnego przepisywania systemu: porażka jednego kroku nie zatrzymuje całego projektu.
Czego nie migrować
Najdojrzalsza decyzja migracyjna często brzmi: „tego nie ruszamy”. Nie warto przepisywać modułu tylko dlatego, że jest stary.
Zostaw stary framework, jeśli:
- moduł jest stabilny, rzadko zmieniany i nie obciąża istotnie strony,
- ma dużo ukrytych reguł biznesowych, których nikt już dobrze nie pamięta,
- dotyczy krytycznej konwersji, a nie masz jeszcze testów E2E,
- zależy od globalnego stanu aplikacji bardziej niż wynika z pierwszego audytu,
- przepisywanie nie zmniejszy JS, nie uprości utrzymania i nie odblokuje rozwoju.
Migruj najpierw miejsca, które są jednocześnie kosztowne i względnie izolowane. To tam Astro daje największy zwrot: zmniejszasz ciężar strony bez otwierania całej architektury naraz.
Pułapki, o których warto wiedzieć
- Współdzielony stan między wyspami. Wyspy są odizolowane — nie dzielą stanu Reacta czy store’a Vue „z automatu”. Komunikację między nimi realizuj przez zdarzenia DOM, (działa cross-framework) lub parametry przekazane z rodzica Astro.
client:onlya . Komponent oznaczonyclient:onlynie renderuje się na serwerze, więc nie pojawi się w pierwszym HTML — zadbaj o sensowny placeholder, by uniknąć przeskoku layoutu.- Globalny CSS. Stare aplikacje często zakładają jeden globalny arkusz. Po przeniesieniu do Astro łatwo o przecieki styli między wyspami. Krytyczne moduły izoluj przez CSS Modules, scoped styles, klasy z prefiksem albo osobny wrapper.
- Różne wersje zależności. Dwa moduły mogą wymagać innych wersji biblioteki UI, klienta API albo helperów dat. Przed migracją sprawdź lockfile i bundle, bo „działa lokalnie” nie znaczy, że koszt produkcyjny jest akceptowalny.
- Analityka i tracking. Jeśli stary komponent wysyła eventy konwersji, migracja musi zachować nazwy eventów, parametry i moment wysyłki. Inaczej poprawisz architekturę, ale popsujesz dane marketingowe.
- Zbyt szybkie przepisywanie. Jeśli pierwszy krok zmienia framework, UI, logikę i tracking jednocześnie, nie będziesz wiedzieć, co zepsuło produkcję. Najpierw opakuj, potem upraszczaj.
Kiedy Astro nie jest właściwą warstwą
Astro jest świetne jako warstwa dla stron treściowych, marketingowych, dokumentacyjnych i hybrydowych. Nie jest jednak automatycznie najlepszym rdzeniem dla każdej aplikacji legacy.
Nie pchałbym całego produktu do Astro, w sytuacji, kiedy:
Większość ekranów wymaga logowania i dynamicznych danych użytkownika
Komponenty współdzielają dużo stanu w czasie rzeczywistym
- Routing aplikacyjny jest częścią logiki produktu
Zespół ma już spójny stack i nie ma realnego problemu migracyjnego
Plan wymaga kilku frameworków na stałe, a nie przejściowo
- Każda wyspa musi stale rozmawiać z każdą inną wyspą
W takim układzie lepsza może być aplikacja w jednym frameworku, a Astro jako osobny front marketingowy, blog, dokumentacja lub publiczna baza wiedzy. Granica jest prosta: jeśli użytkownik głównie czyta i wykonuje punktowe interakcje, Astro pasuje. Jeśli użytkownik pracuje w aplikacji przez wiele ekranów i cały czas zmienia stan systemu, jeden framework aplikacyjny będzie zdrowszy.
