Startseite / Artikel / Reines React Native, Expo oder Flutter: Die Auswahl des mobilen Frameworks für Ihr Team

Reines React Native, Expo oder Flutter: Die Auswahl des mobilen Frameworks für Ihr Team

Ein praktischer Vergleich von reinem React Native, Expo und Flutter: Wie sieht jeder in Code aus, wo liegen die Schwächen jedes Tools, sowie ein fünf Fragen umfassendes Framework zur Entscheidungsfindung zwischen ihnen.

2627 Wörter

Früher war die Wahl eines plattformunabhängigen mobilen Entwicklungsumfelds eine Frage danach, mit welchem Kompromiss man leben konnte. Heute können React Native, Expo und Flutter alle Apps liefern, die sich wie natives Software erweisen, reibungslos laufen und auf sehr große Zielgruppen skalieren – weshalb die reine Geschwindigkeit nur selten entscheidend ist. Entscheidend sind vielmehr die passenden Faktoren: Die Fähigkeiten Ihres Teams, der bereits vorhandene Code sowie die Geschwindigkeit, mit der Sie die Apps in den App Stores bringen müssen. Dieser Artikel betrachtet Expo als eigenständige Option und nicht nur als Nebenbemerkung zu React Native, erläutert in der Praxis, wie jede Option aussieht, und endet mit einer kurzen Reihe von Fragen, die Sie zur Auswahl nutzen können.

Was hat sich in allen drei Umgebungen geändert

Mehrere strukturelle Schwächen, die frühere Vergleiche prägten, wurden beseitigt:

  • Die neue Architektur von React Native ist nun Standard. Sie ersetzt die veraltete asynchrone Brücke, wodurch JavaScript und natives Code direkter miteinander kommunizieren können. Dadurch sind Aufrufe an native Module erheblich kostengünstiger.
  • Der Impeller-Renderer von Flutter hat Skia auf mobilen Geräten als Standard ersetzt. Impeller kompiliert seine Shader im Voraus, was die durch die Shader-Kompilierung beim ersten Start verursachte Verzögerung beseitigt und die Frame-Raten konstanter hält.
  • Expo ist zur Standardmethode zum Erstellen von React Native-Apps geworden. Es handelt sich nicht mehr um einen Sandbox für Anfänger, sondern um eine Produktions-Toolkette, die von großen Unternehmen genutzt wird.

Veröffentlichte Benchmarks deuten darauf hin, dass Flutter bei der Renderleistung in animationsreichen Benutzeroberflächen leicht vorn liegt, während React Native bei der Startzeit, dem Speicherverbrauch sowie den nativen Eingabe/Ausgabe-Vorgängen vorteilhaft ist. Gehen Sie mit konkreten Zahlen vorsichtig um, da sie je nach Anwendung und Gerät stark variieren. Bei den meisten Produkten ist der Unterschied nicht mehr entscheidend für das Endergebnis. Wenn Sie die Sichtweise von Teams erfahren möchten, die bereits seit längerer Zeit mit diesen Entscheidungen umgehen, behandelt unser Artikel zu den Entscheidungen zwischen Flutter und React Native, die erst in der Produktion deutlich werden die langfristigen Aspekte.

Einfaches React Native: maximale Kontrolle, maximale Verantwortung

React Native ermöglicht es Ihnen, die Benutzeroberfläche in JavaScript oder TypeScript mit React zu schreiben, während das Framework echte Plattformkomponenten für iOS und Android darstellt. Es gibt weder einen WebView noch ein benutzerdefiniertes Canvas: Ein View wird zu einer nativen Ansicht und ein Text zu einer nativen Textkomponente.

Die untenstehende Zählung zeigt die grundlegende Struktur einer App im Rahmen der Neuen Architektur mit dem Fabric-Renderer. Der Zustand wird über den useState-Hook verwaltet, der Button ist ein Pressable, und die Styles werden einmal mit StyleSheet.create deklariert, damit sie überprüft und wiederverwendet werden können.

// App.tsx — React Native (New Architecture, Fabric)
import React, { useState } from 'react';
import { View, Text, Pressable, StyleSheet } from 'react-native';

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <View style={styles.container}>
      <Text style={styles.counter}>{count}</Text>
      <Pressable style={styles.button} onPress={() => setCount(c => c + 1)}>
        <Text style={styles.buttonText}>Tap me</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
  counter: { fontSize: 48, fontWeight: '700', marginBottom: 24 },
  button: { backgroundColor: '#2563eb', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 12 },
  buttonText: { color: 'white', fontSize: 16, fontWeight: '600' },
});

Im Wesentlichen enthält dieser Auszug nichts, was spezifisch für die Neue Architektur ist; derselbe Komponentencodierung läuft in beiden Architekturen. Die Änderung der Architektur findet im Hintergrund statt, genauer gesagt in der Art und Weise, wie Renderer und native Module mit JavaScript kommunizieren.

Vorteile

  • Echte natives Widgets. Sie erhalten die eigenen Steuerelemente der Plattform, das Zugänglichkeitsverhalten sowie die Textdarstellung – und nicht nur eine Annäherung daran.
  • Der größte Talentpool. Fähigkeiten in JavaScript, TypeScript und React sind weitaus verbreiteter als die für die anderen Optionen.
  • Vollständiger nativer Zugriff. Sie besitzen die ios/- und android/-Verzeichnisse, sodass Sie jederzeit auf Swift, Kotlin, Objective-C oder Java zurückgreifen können.
  • Ein riesiges Ökosystem. npm bietet mehr Drittanbieter-Pakete als pub.dev, und die meisten mobilen SDKs für Zahlungen, Karten und Analytik liefern offizielle React Native-Wrapper.
  • Schnellere native Aufrufe. Fabric, TurboModules und JSI beseitigen das alte asynchrone Brückenproblem, wodurch Aufrufe im nativen Code nahezu sofort erfolgen.
  • Code-Teilung mit der Web-Plattform. Mit React Native Web kann ein Team, das bereits eine React-Web-Anwendung besitzt, einen Großteil der Logik sowie sogar einige Komponenten wiederverwenden.
  • Schwächen

    • Die native Build-Tooling-Lösung muss selbst bereitgestellt werden. Versionenunterschiede von Xcode, Gradle und CocoaPods sowie Konflikte bei nativen Abhängigkeiten bleiben ein häufiges Problem.
    • Die Konsistenz auf verschiedenen Plattformen erfordert Aufwand. Da das Framework absichtlich native Widgets abbildet, sehen iOS- und Android-Anwendungen unterschiedlich aus, es sei denn, man plant gezielt nach Konsistenz.
    • Die Lieferinfrastruktur muss selbst aufgebaut werden. CI/CD, Code-Signing und Over-the-Air-Updates sind nicht einfach selbst zu implementieren – genau diese Lücke füllt Expo.
    • Uneinheitliche Drittanbieter-Module. Die Wartungsqualität der nativen Module reicht von hervorragend bis völlig vernachlässigt.

    Praktische Ratschläge

    • Vermeiden Sie es, ein neues Projekt in reinem React Native zu starten, es sei denn, Sie haben einen konkreten Grund – wie beispielsweise ein sehr spezifisches natives SDK oder eine bereits vorhandene native Anwendung, die Sie schrittweise migrieren möchten. Beginnen Sie mit Expo und erzeugen Sie native Projekte nur dann, wenn sie benötigt werden.
    • Verwenden Sie react-native-reanimated und react-native-gesture-handler für auf Leistung angewiesene Interaktionen. Sie führen Animationen und Gesten im UI-Thread aus, sodass ein überlasteter JavaScript-Thread keine Frame-Verluste verursacht.
    • Lassen Sie Hermes aktiviert – es ist der Standard-Engine. Er kompiliert JavaScript im Voraus in Bytecode, was die Startzeit und den Speicherverbrauch im Vergleich zu JavaScriptCore deutlich verringert.

    Expo: React Native mit integrierter Infrastruktur

    Expo ist ein Framework sowie eine Reihe von Diensten, die auf React Native aufbauen. Früher galt es als Umgebung mit eingeschränktem Zugriff auf native Code – das gilt heute nicht mehr: Durch Prebuild, auch kontinuierliche native Generierung (CNG) genannt, arbeitet Expo mit dem gesamten Ökosystem nativer Module.

    Der untenstehende Bildschirm verwendet Expo Router, der Dateien im Verzeichnis app/ auf Routen abbildet, genauso wie Next.js es für die Web-Plattform tut. app/index.tsx ist die Startseite, und router.push('/profile') navigiert zur Datei, die /profile definiert. Deep Links sowie Web-URLs folgen derselben Struktur.

    // app/index.tsx — Expo Router (file-based routing)
    import { View, Text, Pressable } from 'react-native';
    import { useRouter } from 'expo-router';
    
    export default function HomeScreen() {
      const router = useRouter();
    
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', gap: 16 }}>
          <Text style={{ fontSize: 24, fontWeight: '600' }}>Welcome</Text>
          <Pressable onPress={() => router.push('/profile')}>
            <Text style={{ color: '#2563eb' }}>Go to Profile</Text>
          </Pressable>
        </View>
      );
    }
    

    Um ein Projekt zu erstellen und auszuführen, sind drei Befehle erforderlich. Der erste erstellt die Grundstruktur der Anwendung, und npx expo start startet den Entwicklungsserver, damit man die Anwendung auf einem Gerät oder Simulator öffnen kann.

    # Spin up a new project in under a minute
    npx create-expo-app@latest my-app
    cd my-app
    npx expo start
    

    Stärken

    • Keine eingebauten Tools zum Einstieg. Für den größten Teil der Entwicklung benötigen Sie weder Xcode noch Android Studio; Sie können auf einem physischen Gerät mit Expo Go oder einem benutzerdefinierten Entwicklungsclient testen.
    • EAS Build. Die Erstellung von iOS- und Android-Anwendungen erfolgt in der Cloud von jedem Betriebssystem aus, sodass Sie eine iOS-Anwendung auch unter Windows oder Linux erstellen können.
    • EAS Update. Over-the-Air-Updates liefern JavaScript-Änderungen sowie Änderungen an Assets sofort an die Nutzer, ohne auf eine Überprüfung im Store warten zu müssen – vorausgesetzt, es gibt keine Änderungen am nativen Code.
    • Expo Router. Dateibasiertes Routing mit Deep Linking sowie universelle Navigation für Web- und native Anwendungen sind direkt verfügbar.
  • Ein umfangreiches, sorgfältig ausgewähltes SDK. Pakete wie expo-camera, expo-notifications, expo-location und expo-image sind integriert, dokumentiert und auf dieselbe Version abgestimmt, sodass sie zusammen funktionieren.
  • Konfigurations-Plugins. Sie können native Projektdateien wie Info.plist und AndroidManifest.xml direkt aus app.json deklarativ ändern, anstatt sie manuell zu bearbeiten – dadurch bleiben die CI-Builds reproduzierbar.
  • Kein Lock-in. Im Grunde handelt es sich weiterhin um React Native. Durch Ausführung von npx expo prebuild werden die nativen Verzeichnisse erzeugt, sobald Sie vollständige Kontrolle über die native Umgebung benötigen.
  • Schwächen

    • Nische SDKs erfordern zusätzliche Arbeit. Einige spezialisierte native SDKs verlangen immer noch, dass man eigene Konfigurations-Plugins oder native Module schreibt – das ist etwas aufwendiger als bei reinem React Native, obwohl der Unterschied stetig schrumpft.
    • Die Falle von Expo Go. Eine starke Abhängigkeit von Expo Go kann verbergen, dass ein benutzerdefiniertes natives Modul erst nach Erstellung einer Entwicklungsversion läuft. Das trifft häufig Neueinsteiger.
    • Dienstkosten. EAS Build und Update bieten kostenlose Versionen, doch ernsthafte Produktionsteams wechseln in der Regel auf kostenpflichtige Pläne – eine Kostenstelle, die reines React Native mit selbst gehostetem CI vermeidet.
    • Vererbte Einschränkungen. Als Schicht über React Native behält Expo seine Nachteile: Abweichungen in der Benutzeroberfläche je nach Plattform sowie ein JavaScript-Thread, der bei intensiver Berechnung zu Engpässen werden kann.

    Praktische Ratschläge

    • Führen Sie npx expo prebuild aus, wenn Sie ein natives Modul benötigen, das von Expo nicht abgedeckt wird. Dadurch werden die Verzeichnisse ios/ und android/ nach Bedarf erstellt, sodass der native Code stets verfügbar ist. Unser Artikel unter Treating Native Folders as Build Output with Expo Prebuild and CNG erläutert den Ablauf ausführlich.
    • Verwenden Sie EAS Update für Hotfixes, nicht jedoch für Funktionen, die das Verhalten des nativen Codes ändern. Die Regeln der App Stores beschränken, was im heruntergeladenen Code geändert werden darf, und das Einspielen neuer Funktionen unter dem Vorwand eines OTA-Updates birgt das Risiko einer Ablehnung; lesen Sie daher vorher die aktuellen Richtlinien von Apple und Google.
    • Führen Sie bei einem neuen Projekt sofort Expo Router ein. Die Anpassung einer auf Dateien basierenden Routing-Logik an eine bereits vorhandene Navigationseinrichtung ist äußerst aufwendig.
  • Führen Sie vor jedem Release-Build expo doctor aus. Es erkennt Abhängigkeits- und Versionsunterschiede, die sonst als unklare Fehler bei der nativen Kompilierung auftreten würden.
  • Flutter: Jeder Pixel unter Kontrolle

    Flutter verfolgt einen grundlegend anderen Ansatz. Anstatt auf Plattform-Widgets zurückzugreifen, zeichnet es die gesamte Benutzeroberfläche mithilfe seines Impeller-Engins selbst, und der Dart-Code wird im Voraus in natives ARM- oder x86-Maschinencode kompiliert.

    Der untenstehende Dart-Counter spiegelt das React Native-Beispiel wider. MyApp umhüllt die Anwendung mit MaterialApp, CounterScreen ist eine StatefulWidget, deren Zustandsklasse _count enthält, und das Drücken der Schaltfläche ruft setState auf, wodurch Flutter aufgefordert wird, diesen Unterbaum mit dem neuen Wert neu zu erstellen.

    // main.dart
    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(home: CounterScreen());
      }
    }
    
    class CounterScreen extends StatefulWidget {
      const CounterScreen({super.key});
    
      @override
      State<CounterScreen> createState() => _CounterScreenState();
    }
    
    class _CounterScreenState extends State<CounterScreen> {
      int _count = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('$_count', style: const TextStyle(fontSize: 48, fontWeight: FontWeight.bold)),
                const SizedBox(height: 24),
                ElevatedButton(
                  onPressed: () => setState(() => _count++),
                  child: const Text('Tap me'),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    Der Workflow über die Kommandozeile umfasst den gesamten Lebenszyklus: Erstellung des Projekts, Ausführung mit Hot Reload während der Entwicklung sowie Erstellung von Veröffentlichungsdateien für Google Play (ein App Bundle) und den App Store (eine IPA).

    flutter create my_app
    cd my_app
    flutter run          # hot reload in under a second
    flutter build appbundle --release   # Android
    flutter build ipa --release         # iOS
    

    Stärken

    • Identische Benutzeroberfläche überall. Da Flutter jedes Widget selbst rendernt, stimmen Verhalten und Aussehen auf iOS, Android, Web und Desktop ohne Plattformbesonderheiten überein.
    • Hervorragende Animationen. Durch im Voraus kompilierte Shader sowie direkten Zugriff auf die GPU über Impeller liegt Flutter in Vergleichen der Bildrate bei komplexen, animierten Benutzeroberflächen in der Regel vorn.
    • Sechs Zielplattformen aus einer Codebasis. iOS, Android, Web, Windows, macOS und Linux werden alle aus demselben Dart-Code erstellt.
  • Hervorragende Entwicklungstools. DevTools, Hot Reload sowie ein konsistentes, gut dokumentiertes Widget-Katalog sorgen dafür, dass der tägliche Entwicklungsprozess angenehm verläuft.
  • Kein Interpreter im Laufzeitpfad. Die Vorab-Kompilierung in Maschinensprache bedeutet, dass es zur Laufzeit keinen JavaScript-Engine oder -Brücke gibt.
  • Ausgereift in großen Systemen. Google unterstützt es, und große Produktionsanwendungen wie Google Pay, BMWs Apps sowie Alibabas Xianyu nutzen es.
  • Schwächen

    • Dart verfügt über ein kleineres Ökosystem. Es ist schwieriger, Entwickler zu finden als für JavaScript oder TypeScript, und selbst erfahrene Entwickler benötigen in der Regel einige Wochen, um produktiv zu werden.
    • Es kann etwas ungewohnt wirken. Da es keine Plattform-Widgets verwendet, können aufmerksame Nutzer leichte Unterschiede im Verhalten feststellen, obwohl diese inzwischen erheblich abgenommen haben.
    • Größere Binärdateien. Der Flutter-Engine ist in jeder App enthalten, wodurch die Pakete in der Regel größer ausfallen als bei einer äquivalenten React Native-App.
    • pub.dev ist gut, aber weniger umfangreich als npm – insbesondere was Wrapper für spezialisierte native SDKs angeht.
    • Keine Wiederverwendung von Web-React-Code. Eine Organisation mit einer etablierten React-Web-Codebasis hat nichts, was sie im Web wiederverwenden könnte.

    Praktische Ratschläge

    • Schalten Sie bereits ab dem ersten Tag flutter analyze mit strengen Lint-Regeln ein. Die Null-Sicherheit von Dart ist tatsächlich ein Vorteil – vorausgesetzt, man vermeidet es, sie durch überall verwendete dynamic-Typen zu untergraben.
    • Wählen Sie für Projekte jenseits eines Prototyps ein State-Management-Verfahren wie Riverpod oder Bloc; setState allein reicht für eine echte App nicht aus.
  • Prüfen Sie die Profilansichten der DevTools unter „Performance“, bevor Sie von einem Problem mit Verzögerungen ausgehen. Impeller hat bereits die meisten Probleme bei der historischen Shader-Kompilierung beseitigt.
  • Falls das Web für Sie wichtig ist, testen Sie Flutter Web frühzeitig. Seine Renderer verhalten sich anders als die für mobile Geräte, und die Größe der Pakete kann überraschend sein. Zum Zeitpunkt dieser Erstellung konzentriert sich Flutter auf seine auf CanvasKit basierenden Renderer – überprüfen Sie daher die aktuelle Dokumentation, um herauszufinden, welche Optionen noch unterstützt werden.
  • Fünf Fragen, die die Entscheidung erleichtern

    Gehen Sie diese Fragen nacheinander durch. Meist entscheidet bereits die erste Frage mit einer klaren Antwort.

    • Arbeitet Ihr Team bereits mit React und JavaScript? Wenn ja, bleiben Sie im React Native-Ökosystem und verwenden Sie standardmäßig Expo. Wenn nicht und Sie frei wählen können, sind sowohl Flutter als auch Expo geeignet – wählen Sie die Sprache, die Ihr Team lieber erlernen würde.
    • Brauchen Sie ein pixelgenaues Design oder umfangreiche, maßgeschneiderte Animationen, wie in Spielen, kreativen Tools oder anspruchsvollen Visualisierungs-Apps? Flutter ist hier die bessere Wahl.
    • Möchten Sie Code oder Komponenten mit einer bestehenden React-Web-App teilen? React Native bietet durch React Native Web einen echten Vorteil; Flutter muss für die Webnutzung neu implementiert werden.
    • Müssen Sie Korrekturen ausschließlich in JavaScript bereitstellen, ohne dass diese einer Store-Prüfung unterzogen werden, oder iOS-Apps ohne Mac entwickeln? Expo’s EAS Update und EAS Build lösen beide Probleme direkt.
    • Einbetten Sie plattformübergreifende Benutzeroberflächen in eine große, bereits vorhandene native App? Reines React Native oder Flutters Unterstützung zur Erweiterung bestehender Apps eignet sich dafür besser als ein neues Expo-Projekt.

    Empfehlungen

    • Für ein React- oder JavaScript-Team, das eine neue App entwickelt, wählen Sie Expo. Es beseitigt die meisten bisherigen Probleme von React Native im Zusammenhang mit Tools für native Entwicklung, CI/CD-Prozessen und OTA-Updates, während es bei Bedarf weiterhin die volle Leistungsfähigkeit nativer Lösungen bietet.
    • Wählen Sie Flutter, wenn die Optik der Benutzeroberfläche, die Leistung von Animationen sowie die Verfügbarkeit auf Mobilgeräten, Desktop-Systemen und im Web wichtiger sind als die Wiederverwendung des JavaScript-Ecosystems – oder wenn Ihr Team keine klare Präferenz für eine Sprache hat und von vorne anfängt.
    • Bewahren Sie sich React Native in seiner reinen Form auf für Situationen, in denen die direkte Verwaltung der nativen Projekte erforderlich ist – typischerweise bei einer großen bestehenden native Codebasis oder ungewöhnlichen Anforderungen an die nativen Integrationen.

    Zusammenfassung

    Die drei Frameworks haben in Bezug auf Leistung und Reifegrad ausreichend an Geschwindigkeit zugelegt, sodass die Funktionalitäten des Frameworks selten zum Engpass werden. Entscheidend sind die Personen in Ihrem Team, der bereits vorhandene Code sowie die Geschwindigkeit, mit der Sie das Produkt veröffentlichen müssen. Betrachten Sie Expo als die Standardmethode zur Verwendung von React Native, reservieren Sie reines React Native für Fälle, in denen die Kontrolle über die nativen Projekte im Vordergrund steht, und wählen Sie Flutter, wenn die Kontrolle über das Rendering sowie der Zugang zu mehreren Plattformen den Vorteil des Verbleibs in JavaScript überwiegen. Unabhängig von Ihrer Wahl sollten Sie den riskantesten Teil Ihrer Anwendung – sei es ein natives SDK, eine komplexe Animation oder die Web-Version – bereits in den ersten Wochen prüfen und nicht erst zum Zeitpunkt der Veröffentlichung.