Aktualizacja starej aplikacji we Flutterze lub React Native — jak podnieść framework po latach

Aplikacja we Flutterze lub React Native nie była aktualizowana od lat i nie chce się zbudować? Co najczęściej blokuje aktualizację (null safety, nowa architektura, Gradle, 16 KB), w jakiej kolejności podnosić stos i ile to trwa.

Zespół Mobilesoft· Engineering team· 12 października 2026· 6 min czytania

Aplikacja w Flutterze albo React Native, napisana trzy, cztery lata temu. Działa, użytkownicy są zadowoleni, nikt jej nie ruszał od ostatniego wydania. Teraz trzeba wypuścić aktualizację — bo sklep wymaga nowego targetSdk, bo jest błąd do poprawienia albo bo w końcu jest budżet na nową funkcję. Programista uruchamia flutter build albo npx react-native run-android i dostaje kilkaset linii błędów.

To jedna z najczęstszych sytuacji w projektach, które przejmujemy. Dobra wiadomość: prawie zawsze da się ją rozwiązać bez przepisywania aplikacji od zera. Trzeba tylko wiedzieć, co dokładnie się zestarzało i w jakiej kolejności to podnosić.

Dlaczego aplikacja wieloplatformowa starzeje się podwójnie

Aplikacja natywna zależy od dwóch rzeczy: Androida i iOS. Aplikacja we Flutterze lub React Native zależy od czterech warstw, które starzeją się w różnym tempie:

  1. Wymagania sklepów — Google Play od 31 sierpnia 2026 wymaga, żeby aktualizacje celowały w Androida 16 (API 36), a App Store od 28 kwietnia 2026 przyjmuje tylko aplikacje zbudowane w Xcode 26.
  2. Natywne narzędzia — Gradle, Android Gradle Plugin, wersja Javy i Kotlina, Xcode, CocoaPods.
  3. Framework — Flutter i Dart albo React Native.
  4. Biblioteki — pakiety z pub.dev albo npm, z których każdy ma własną część natywną.

Problem polega na tym, że te warstwy są ze sobą sprzężone. Żeby spełnić wymaganie sklepu, trzeba podnieść natywne narzędzia. Nowe narzędzia nie współpracują ze starym frameworkiem. Nowy framework nie współpracuje ze starymi bibliotekami. A część bibliotek przez te lata przestała być rozwijana. Dlatego „tylko podnieść targetSdk” w zaniedbanym projekcie wieloplatformowym zamienia się w aktualizację całego stosu. Szerzej o samym terminie Google Play piszemy w tekście o tym, dlaczego aplikacja znika z Google Play po terminie target API.

Flutter: co zwykle blokuje aktualizację

Null safety i Dart 3. Od Fluttera 3.10 (maj 2023) Dart wymaga pełnego sound null safety. Projekt, który nigdy nie przeszedł migracji, nie skompiluje się na żadnej nowej wersji Fluttera. Migrację można częściowo zautomatyzować, ale przy dużym kodzie to i tak najbardziej pracochłonny element — i wymaga zrozumienia, które wartości faktycznie mogą być puste.

Konfiguracja Gradle. Projekty utworzone przed 2023 rokiem stosują wtyczkę Fluttera do Gradle w starym, imperatywnym stylu. Nowsze wersje Fluttera wymagają stylu deklaratywnego (blok plugins {}). Oficjalny przewodnik migracji opisuje to krok po kroku, ale w projektach z własnymi modyfikacjami plików Gradle zawsze wychodzi coś nieprzewidzianego. Bardzo stare projekty mogą jeszcze używać pierwszej wersji osadzenia Fluttera w Androidzie (v1 embedding), której obsługa została usunięta.

Porzucone pakiety. pub.dev oznacza pakiety jako discontinued, często wskazując następcę. Polecenie flutter pub outdated pokazuje, jak daleko w tyle są zależności; po aktualizacji dart fix --apply automatycznie poprawia część zmian w API.

React Native: co zwykle blokuje aktualizację

Nowa architektura. React Native od wersji 0.76 (październik 2024) domyślnie używa nowej architektury, a od wersji 0.82 (październik 2025) stara architektura nie jest już wspierana. Aplikacja na wersji sprzed 0.76 musi więc przejść na nową architekturę — a to oznacza, że każda biblioteka z natywnym kodem musi ją obsługiwać. Katalog reactnative.directory pozwala filtrować biblioteki pod tym kątem. Biblioteki, które nigdy nie zostały zaktualizowane, trzeba zastąpić albo przepisać ich natywną część.

Skok o wiele wersji. Każda wersja React Native zmienia pliki natywne projektu — build.gradle, Podfile, AppDelegate. Narzędzie Upgrade Helper pokazuje różnice między dowolnymi dwiema wersjami. Przy skoku o kilka wersji da się je nanieść ręcznie; przy skoku o kilkanaście zwykle szybciej jest utworzyć czysty projekt na aktualnej wersji i przenieść do niego kod aplikacji, niż walczyć z łańcuchem konfliktów.

Expo. Projekty na Expo mają łatwiej, bo Expo zarządza natywną konfiguracją. Zalecana droga to podnoszenie po jednej wersji SDK naraz i npx expo install --fix po każdej, żeby dopasować wersje bibliotek. Kłopotliwe bywają projekty, które kiedyś zrobiły eject i od tego czasu mają ręcznie modyfikowane katalogi android i ios.

Minimalne wersje systemów. Kolejne wydania React Native — podobnie jak Fluttera — podnoszą minimalną wspieraną wersję Androida i iOS. Przed aktualizacją sprawdź w statystykach sklepu, ilu użytkowników korzysta z wersji, które przestaniesz wspierać.

Wspólne dla obu: warstwa natywna

Niezależnie od frameworka, w 2026 roku trzeba się liczyć z kilkoma natywnymi wymaganiami:

  • Strony pamięci 16 KB na Androidzie. Google Play wymaga, żeby aplikacje celujące w Androida 15 i nowszego działały na urządzeniach z 16-kilobajtowymi stronami pamięci. Dotyczy to natywnych bibliotek (.so) — a w aplikacjach Flutter i React Native jest ich zawsze sporo, choćby sam silnik frameworka. Stare wersje frameworków i bibliotek tego nie spełniają.
  • Edge-to-edge. Przy targetSdk 36 aplikacja nie może już zrezygnować z rysowania pod paskami systemowymi — interfejs musi poprawnie obsługiwać marginesy.
  • Xcode 26 i Liquid Glass. Aplikacja zbudowana nowym SDK iOS dostaje nowy wygląd standardowych komponentów. Więcej o tym w tekście o tym, co zmieniło się w nowym Androidzie i iOS.
  • CocoaPods. Zespół CocoaPods zapowiedział, że centralne repozytorium specyfikacji przejdzie w tryb tylko do odczytu pod koniec 2026 roku. Istniejące zależności nadal da się instalować, ale nowe wersje bibliotek będą publikowane przez Swift Package Manager. Flutter i React Native mają już obsługę SPM — przy dużej aktualizacji warto zaplanować przejście od razu.

Kolejność, która oszczędza czas

  1. Odtwórz obecny stan. Zanim cokolwiek zaktualizujesz, zbuduj aplikację w obecnej wersji — nawet jeśli wymaga to starej wersji Fluttera, Node, Javy czy Xcode. Bez działającego punktu odniesienia nie odróżnisz błędów aktualizacji od błędów, które były w aplikacji od zawsze.
  2. Spisz kluczowe ścieżki. Logowanie, płatności, powiadomienia, najważniejsze ekrany. Jeśli projekt nie ma testów automatycznych, wystarczy lista do ręcznego sprawdzenia — ale musi istnieć, zanim zaczniesz.
  3. Przejrzyj zależności. Każdą bibliotekę zaklasyfikuj: aktualizować, zastąpić, usunąć. Często okazuje się, że część bibliotek jest nieużywana albo wykorzystywana do jednej drobnej rzeczy, którą łatwiej napisać samemu.
  4. Wybierz ścieżkę. Przy małym skoku — aktualizacja wersja po wersji. Przy dużym — czysty projekt na aktualnej wersji frameworka i przeniesienie kodu. Druga ścieżka wydaje się większa, ale zwykle jest bardziej przewidywalna.
  5. Oddziel aktualizację od nowych funkcji. Pierwsze wydanie po aktualizacji powinno wyglądać i działać tak samo jak poprzednie. Jeśli coś się zepsuje, będzie wiadomo, gdzie szukać.
  6. Wydawaj stopniowo. Staged rollout w Google Play i phased release w App Store pozwalają wypuścić nową wersję do części użytkowników i obserwować awarie, zanim trafi do wszystkich.

Ile to trwa

Zależy przede wszystkim od skoku wersji i stanu bibliotek, a nie od wielkości aplikacji. Orientacyjnie:

Sytuacja Typowy nakład Framework sprzed roku, biblioteki rozwijane kilka dni Framework sprzed 2–3 lat, kilka bibliotek do zastąpienia dwa–cztery tygodnie Flutter bez null safety albo React Native sprzed nowej architektury z porzuconymi bibliotekami natywnymi od miesiąca wzwyż, zależnie od ilości kodu

To widełki, nie wycena — dokładną liczbę da się podać dopiero po przejrzeniu projektu. Czasem po takim przeglądzie wychodzi, że część aplikacji lepiej napisać na nowo; o tym, jak podjąć tę decyzję na liczbach, piszemy w tekście refactor czy przepisać od zera.

Jak nie wrócić tu za trzy lata

Aktualizacja o rok to kilka dni pracy. Aktualizacja o cztery lata to projekt. Różnica nie wynika z tego, że zmian jest cztery razy więcej, tylko z tego, że nakładają się na siebie i trzeba je przechodzić wszystkie naraz. Najtańsza strategia to regularne, małe aktualizacje — framework i biblioteki podnoszone co kilka miesięcy, w ramach zwykłego utrzymania, razem z coroczną zmianą wymagań sklepów.

Aktualizujemy i utrzymujemy aplikacje we Flutterze i React Native, także te, których od lat nikt nie ruszał — w ramach reaktywacji aplikacji, a potem utrzymania aplikacji mobilnych. Jeśli chcesz wiedzieć, jak daleko w tyle jest Twój projekt i ile pracy dzieli go od kolejnego wydania, zamów bezpłatną analizę aplikacji — wynik dostaniesz na piśmie.