Vue 2 jest po terminie wsparcia. Twoja aplikacja nie.
Vue 2 przestał być wspierany 31 grudnia 2023 roku, a Nuxt 2 — 30 czerwca 2024 roku. Aplikacje zbudowane na tych technologiach jednak nie zniknęły. Klienci nadal z nich korzystają, nowe funkcje nadal trzeba dostarczać, a istniejący kod nadal trzeba utrzymywać.
W tym właśnie zaczyna się prawdziwy problem migracji. Z czasem aktualizacje stają się trudniejsze, stare zależności zostają w projekcie na dłużej, a kolejne fragmenty kodu stają się coraz droższe w zmianie. Migracja pozwala usunąć to ograniczenie, ale powinna być zaplanowana wokół Twojej aplikacji, a nie potraktowana jak zwykła zmiana numeru wersji.
Od ponad dekady tworzę produkcyjne frontendowe aplikacje, ze szczególnym doświadczeniem w Vue i Nuxt. Migrację Vue 2 do Vue 3 traktuję jako projekt inżynierski z konkretnym efektem: przejście na zdrowszą bazę kodu bez tworzenia kolejnego systemu, który za kilka lat znów będzie wymagał ratowania.
Migracja etapami czy przepisanie od zera?
Nie ma jednej właściwej odpowiedzi. Sposób migracji zależy od kodu, produktu i tego, jak zespół musi pracować w czasie całego procesu.
- Które części aplikacji nadal się zmieniają? Obszary, do których co miesiąc trafiają nowe funkcje, często warto przy okazji uporządkować. Stabilne fragmenty można zwykle przenieść przy mniejszej liczbie zmian.
- Czy rozwój produktu może się zatrzymać? Jeśli biznes musi cały czas dostarczać nowe funkcje, migracja etapami pozwala pracować nad nową wersją bez czekania na zakończenie wielomiesięcznego rewrite'u.
- Jakie problemy naprawdę ma obecny kod? Jeśli architektura cierpi z powodu ukrytego couplingu, niejasnego przepływu danych, niespójnych konwencji czy trudnych do wyznaczenia granic modułów, sama zmiana wersji Vue tych problemów nie usunie.
- Gdzie przebiegają rzeczywiste granice aplikacji? To często decyduje o tym, czy system da się sensownie migrować fragmentami, czy obecna struktura bardziej przemawia za większym rewrite'em.
Wolę dojść do takiego wniosku po krótkim przejrzeniu repozytorium niż po trzech miesiącach migracji.
Na co patrzę przed zmianą kodu
Migracja daje rzadką okazję, żeby zakwestionować elementy aplikacji, które przez lata pozostawały na swoim miejscu tylko dlatego, że już tam były. Zanim zacznę przenosić komponenty z Vue 2 do Vue 3, patrzę na strukturę, która je otacza.
Obejmuje to granice modułów, współdzielone zależności, zarządzanie stanem, dostęp do API, sposób obsługi zapytań i cache'u, wspólne komponenty oraz konwencje, na których zespół opiera codzienną pracę. Chodzi o to, żeby wiedzieć, co można przenieść bez większych zmian, co warto uporządkować przy okazji migracji, a co lepiej usunąć zamiast przenosić.
Szukam również zależności, które utrudnią migrację etapami. Cykliczne importy, współdzielone moduły bez jasno określonej odpowiedzialności czy rozrzucone po całej aplikacji utility potrafią zamienić pozornie prostą migrację w serię pozornie niezależnych zmian.
Migracja to także okazja do poprawy produktu
Nie każda wymiana legacy zaczyna się od Vue 2. Zbudowałem również od zera następcę aplikacji opartej na KnockoutJS.
Był to tygodniowy planer posiłków, który powstał we Vue 3 i TypeScript. Zaproponowałem drag & drop jako główny sposób interakcji. Zamiast przeklikiwania kolejnych formularzy planowanie tygodnia polegało na bezpośrednim układaniu elementów na ekranie.
Ta sama zasada dotyczy migracji Vue 2. Jeżeli dany ekran i tak wymaga większych zmian, warto sprawdzić, czy jego obecny sposób działania nadal ma sens. Migracja może być dobrym momentem na poprawę problematycznego workflow, a nie tylko na odtworzenie go w nowszej technologii.
Nowa aplikacja też może odziedziczyć stare problemy
Jednej z najlepszych lekcji nauczyłem się podczas dużego rewrite'u aplikacji na Vue 3 dla firmy cateringowej. Stack był nowoczesny, architektura feature-based, dane obsługiwane przez TanStack Query, a aktualizacje w czasie rzeczywistym dostarczał SignalR. Mimo to aplikacja była wolna jeszcze przed wdrożeniem.
Przyczyny nie były związane z samym Vue. Zagnieżdżone pętle wykonywały
niepotrzebną pracę, część watchEffect uruchamiała się ponownie
wskutek reakcji łańcuchowych, TanStack Query był używany jak globalna szyna
zdarzeń, a reaktywne zapytania tworzyły kaskady, w których jedno wywołanie
uruchamiało kolejne.
Rozdzieliłem odpowiedzialności pomiędzy moduły i widoki, wprowadziłem bardziej restrykcyjne reguły projektu z użyciem Biome i git hooków, scentralizowałem klientów API, queries, mutations i query keys w jednej typowanej warstwie danych oraz zbudowałem mechanizm inwalidacji sterowany zdarzeniami SignalR. Dzięki temu konkretna wiadomość mogła unieważniać tylko te zapytania, których rzeczywiście dotyczyła.
Efektem była aplikacja Vue 3 bez pozostałych kaskad requestów oraz znacznie bardziej przejrzysty sposób przepływu danych. Całą historię opisuję w case study o ratowaniu wydajności.
To właśnie ryzyko związane z traktowaniem migracji jak ćwiczenia ze składni: jeśli stara architektura i stare sposoby pracy zostaną przeniesione do nowego kodu, aplikacja będzie nowsza, ale niekoniecznie łatwiejsza w utrzymaniu.
Nuxt i struktura wokół aplikacji
Dla wielu zespołów przejście na Vue 3 oznacza również przejście na nowszy stack Nuxt. Mam doświadczenie z Nuxt 4 i Payload CMS 3. Zbudowałem między innymi serwis dla schroniska dla zwierząt, oparty o Postgresa i Lexical, działający w monorepo pnpm, ze wspólną biblioteką komponentów w Storybooku i wdrożeniem opartym na Dockerze.
To doświadczenie jest istotne przy migracji, ponieważ docelowa architektura również musi być wygodna w codziennej pracy i wdrażaniu. Celem nie jest samo uruchomienie aplikacji na nowszej wersji Vue, ale pozostawienie zespołowi kodu i środowiska, które można dalej rozwijać bez dokładania kolejnych ograniczeń.
Zbudowałem również rds — open-source'owe narzędzie w Rust do wykrywania cyklicznych zależności w aplikacjach Node.js i TypeScript. Przy planowaniu migracji stosuję podobne podejście: najpierw sprawdzam, gdzie kod jest ze sobą powiązany, a dopiero potem wyznaczam granice, które pozwalają podzielić pracę na sensowne etapy.
Co powinna zostawić po sobie migracja
Udana migracja to coś więcej niż zestaw komponentów przepisanych na Vue 3. Jej efektem powinien być kod, w którym kolejna zmiana jest prostsza niż w poprzedniej wersji.
- Zdrowsza architektura Vue 3. Wyraźniejsze granice modułów, sensowna warstwa danych i mniej ukrytych zależności.
- Spójne zasady pracy. Linting, formatowanie, sprawdzanie typów oraz git hooki działają automatycznie, więc jakość kodu nie zależy wyłącznie od tego, jak dokładnie ktoś przejrzy pull request.
- Plan migracji dopasowany do rzeczywistej aplikacji. Co migrować najpierw, co może poczekać, które fragmenty wymagają redesignu, a czego nie warto już przenosić.
- Zespół, który może pracować dalej bez konsultanta. Pracuję razem z developerami i wyjaśniam decyzje stojące za migracją, żeby wiedza została w zespole, zamiast odejść razem ze mną.
Nie wiesz, czy Twoja aplikacja potrzebuje pełnej migracji, podejścia etapowego czy może szerszego przeglądu architektury? Mogę zacząć od repozytorium i pomóc ustalić, co rzeczywiście warto zmienić. Audyt wydajności frontendu może być również dobrym punktem wyjścia, jeśli wydajność jest jednym z powodów rozważania rewrite'u.
Jeśli aplikacja jest częścią większej platformy złożonej z wielu aplikacji, moje doświadczenie z architekturą mikrofrontendów pozwala spojrzeć na migrację w kontekście systemu, a nie tylko pojedynczego repozytorium.
Jestem dostępny part-time, w modelu B2B, zdalnie. Opowiedz mi o swojej aplikacji w Vue 2, a odpowiem w ciągu jednego dnia roboczego.