Powrót do strony głównej

Ręczne aktualizowanie bundli Capacitor bez sklepów

Artykuł opisuje ręczną integrację @capgo/capacitor-updater dla aktualizacji OTA bundli JS aplikacji Capacitor. Podano przykłady kodu providera, przygotowanie archiwów za pomocą CLI, sprawdzenie zgodności z zasadami sklepów. Nadaje się dla deweloperów middle/senior.

Capacitor: aktualizacja bundli omijająca zatwierdzenie sklepów
Advertisement 728x90

Ręczne aktualizowanie bundli Capacitor bez sklepów z aplikacjami

Aplikacje mobilne na Capacitor wymagają pełnego wydania w sklepach nawet dla drobnych poprawek w kodzie JS lub specyfikacjach. Bez zmian w kodzie natywnym proces zatwierdzania w Google Play, RuStore, AppGallery i App Store trwa dniami. Automatyzacja pomaga, ale moderacja jest nieunikniona.

Rozwiązanie polega na aktualizacji zawartości katalogu dist (lub build) bez ponownego budowania części natywnej. Plugin @capgo/capacitor-updater umożliwia zdalną wymianę bundla w trybie ręcznym lub automatycznym.

Zgodność z zasadami sklepów

Aktualizacje bundli JS są dozwolone przez wszystkie platformy pod warunkiem spełnienia warunków:

Google AdInline article slot
  • Google Play: interpretowalny kod (JS) jest dopuszczalny, o ile nie narusza zasad nadużywania zasobów.
  • App Store: ładowany kod nie zmienia przeznaczenia aplikacji, nie tworzy sklepu z kodem i nie omija zabezpieczeń WebView.

Warunki te są spełniane automatycznie dla aplikacji hybrydowych na Capacitor.

Instalacja i konfiguracja

Zainstaluj zależności:

npm i @capgo/capacitor-updater compare-versions

W capacitor.config.ts dodaj:

Google AdInline article slot
plugins: {
  CapacitorUpdater: {
    autoUpdate: false,
  },
},

Tryb autoUpdate: false włącza ręczne zarządzanie aktualizacjami.

Utwórz provider AppUpdateProvider dla React (dostosuj do frameworka):

const AppUpdateProvider: FC<PropsWithChildren> = ({ children }) => {
  return children;
};

export default AppUpdateProvider;

Logika aktualizacji

W providerze wywołaj CapacitorUpdater.notifyAppReady() w ciągu pierwszych 10 sekund od uruchomienia — w przeciwnym razie wystąpi błąd.

Google AdInline article slot

Pobierz dane o najnowszym wydaniu przez API (GitHub lub własny serwis). Porównaj wersje za pomocą compare-versions.

Przykład pełnego useEffect:

useEffect(() => {
  if (appRelease === null) {
    dispatch(getAppRelease({ type: ReleaseType.APP, last: true }));
  } else {
    const downloadBundle = async () => {
      dispatch(setAppUpdating(true));
      return CapacitorUpdater.download({
        url: APP_BUNDLE_DOWNLOAD_LINK,
        version: appRelease.version,
      });
    };

    CapacitorUpdater.addListener('downloadComplete', async ({ bundle: downloadedBundle }) => {
      try {
        await CapacitorUpdater.set(downloadedBundle);
        dispatch(setAppUpdating(false));
      } catch (e) {
        console.error(e);
        dispatch(setAppUpdating(false));
      }
    });

    if (compare(String(version), appRelease.version, '<')) downloadBundle();

    return () => {
      CapacitorUpdater.removeAllListeners();
      App.removeAllListeners();
    };
  }
}, [appRelease]);

Przygotowanie bundla

Archiwum bundla utwórz ściśle za pomocą Capgo CLI:

npx @capgo/cli bundle zip [appId] --name [myapp]
  • appId z capacitor.config.ts.
  • Zaktualizuj version w package.json przed budowaniem.
  • Wgraj ZIP na serwer HTTPS (GitHub Releases lub własny hosting).

Link do archiwum przekazuj w CapacitorUpdater.download({ url, version }).

Po pobraniu downloadComplete wywołuje CapacitorUpdater.set() — bundl jest zastępowany, aplikacja uruchamia się ponownie.

Integracja w aplikacji

Pełny provider:

const AppUpdateProvider: FC<PropsWithChildren> = ({ children }) => {
  CapacitorUpdater.notifyAppReady();
  const dispatch = useAppDispatch();
  const appRelease = useAppSelector(selectAppRelease);

  // useEffect jak wyżej

  return children;
};

W main.tsx owiń App:

root.render(
  <Provider store={store({})}>
    <AppUpdateProvider>
      <App />
    </AppUpdateProvider>
  </Provider>
);

Co ważne

  • Aktualizacje działają tylko dla bundla JS, bez natywnych pluginów.
  • Bundl archiwizuj za pomocą npx @capgo/cli bundle zip — inne metody są nieprawidłowe.
  • Wywołanie notifyAppReady() jest obowiązkowe w ciągu pierwszych 10 s od uruchomienia.
  • Porównanie wersji: compare(currentVersion, newVersion, '<').
  • Self-hosted Capgo — alternatywa dla pełnej kontroli.

— Editorial Team

Advertisement 728x90

Czytaj dalej