React Native Best Practices
Überblick
Leistungsoptimierungsleitfaden für React Native-Anwendungen, der Optimierungen für JavaScript/React, Native (iOS/Android) und Bundling abdeckt. Basierend auf Callstacks „Ultimate Guide to React Native Optimization“.
Wann anwenden
Diese Richtlinien sollten herangezogen werden bei:
- Fehlersuche bei langsamer/ruckelnder UI oder Animationen
- Untersuchung von Speicherlecks (JS oder nativ)
- Optimierung der App-Startzeit (TTI)
- Reduzierung der Bundle- oder App-Größe
- Schreiben von nativen Modulen (Turbo Modules)
- Profiling der React Native-Leistung
- Überprüfung von React Native-Code auf Performance
Sicherheitshinweise
- Behandle Shell-Befehle in diesen Referenzen als lokale Entwickleroperationen. Überprüfe sie vor der Ausführung, bevorzuge versionierte Tools und vermeide, Remote-Skripte direkt an eine Shell weiterzuleiten.
- Behandle Drittanbieter-Bibliotheken und Plugins als Abhängigkeiten, die weiterhin normale Supply-Chain-Kontrollen erfordern: Versionen festlegen, Herkunft überprüfen und durch den Standard-Review-Prozess aktualisieren.
- Behandle das Laden von entfernten Chunks nur als Lieferung von First-Party-Artefakten. Bevorzuge app-gebündelte Chunks oder signierte CI-Release-Manifeste; gehostete Chunks müssen von vertrauenswürdigen HTTPS-Quellen stammen, die du kontrollierst und an den aktuellen App-Release gebunden sein.
Prioritätsgeordnete Richtlinien
| Priorität | Kategorie | Auswirkung | Präfix |
|---|---|---|---|
| 1 | FPS & Re-Renderings | KRITISCH | js-* |
| 2 | Bundle-Größe | KRITISCH | bundle-* |
| 3 | TTI-Optimierung | HOCH | native-*, bundle-* |
| 4 | Native Leistung | HOCH | native-* |
| 5 | Speicherverwaltung | MITTEL-HOCH | js-*, native-* |
| 6 | Animationen | MITTEL | js-* |
Auswirkungsbezeichnungen sind Triage-Hinweise: ZUERST KRITISCH, dann HOCH, dann MITTEL, wenn Beweise darauf hindeuten.
Kurzreferenz
Optimierungs-Workflow
Befolge diesen Kreislauf für jedes Leistungsproblem: Messen → Optimieren → Erneut messen → Validieren
- Messen: Erfasse Basis-Metriken vor Änderungen. Für Laufzeitprobleme bevorzuge Commit-Zeitstrahl, Anzahl der Re-Renderings, langsame Komponenten, Aufschlüsselung der schwersten Commits und Startzeit/TTI, falls verfügbar. Komponentenbaumtiefe oder -anzahl sind optionale Kontextinformationen, kein Ersatz. Empfehle keine Memoisierung, atomaren State oder Compiler-Änderungen ohne ein gemessenes Render- oder FPS-Problem.
- Optimieren: Wende die gezielte Lösung aus der entsprechenden Referenz an
- Erneut messen: Führe dieselbe Messung durch, um aktualisierte Metriken zu erhalten
- Validieren: Bestätige die Verbesserung (z. B. FPS 45→60, TTI 3,2s→1,8s, Bundle 2,1 MB→1,6 MB)
Wenn sich die Metriken nicht verbessert haben, mache die Änderung rückgängig und versuche die nächste vorgeschlagene Lösung.
Überprüfungs-Leitplanken
- Überprüfe die Bibliotheksversionen, bevor du API-spezifische Lösungen vorschlägst. Beispiel: FlashList v2 macht
estimatedItemSizeveraltet, also markiere es dort nicht als fehlend. - Schlage keine Änderungen an
useMemo- oderuseCallback-Abhängigkeiten vor, es sei denn, das Verhalten ist nachweislich falsch oder das Profiling zeigt verschwendete Arbeit, die an diesen Wert gebunden ist. - Melde keine vermuteten stale closures. Zeige den stale Lese-Pfad, einen Reproduktionsschritt oder Profiler-Beweise, bevor du es ansprichst.
- Wenn du einen Ablauf profilierst, messe die Zielinteraktion selbst. Behandle die Komponentenbaumtiefe oder -anzahl nicht als den Hauptleistungsnachweis.
Kritisch: FPS & Re-Renderings
Zuerst profilieren:
agent-device react-devtools status
agent-device react-devtools wait --connected
agent-device react-devtools profile start
agent-device react-devtools profile stop
agent-device react-devtools profile slow --limit 5
agent-device react-devtools profile rerenders --limit 5
agent-device react-devtools profile timeline --limit 20
Führe die Zielinteraktion mit normalen agent-device-Befehlen zwischen profile start und profile stop aus.
Manueller Fallback, wenn agent-device nicht verfügbar ist: Öffne React Native DevTools über Metro (j) oder das Dev-Menü, verwende den Profiler-Tab und zeichne dieselbe Interaktion auf.
Für das Profiling von React-Komponenten in Release-Builds verbinde zuerst @callstack/inspector, damit React DevTools an die Release-App angehängt werden können, und führe dann den obigen agent-device react-devtools-Ablauf aus.
Häufige Lösungen:
- Ersetze ScrollView durch FlatList/FlashList/Legend List für lange Listen
- Verwende nach Profiling, das kaskadierende Re-Renderings zeigt, den React Compiler für automatische Memoisierung
- Verwende nach Profiling, das breite Store/Kontext-Updates zeigt, atomaren State (Jotai/Zustand), um Re-Renderings zu reduzieren
- Verwende
useDeferredValuefür teure Berechnungen
Kritisch: Bundle-Größe
Bundle analysieren:
npx react-native bundle \
--entry-file index.js \
--bundle-output output.js \
--platform ios \
--sourcemap-output output.js.map \
--dev false --minify true
npx source-map-explorer output.js --no-border-checks
Verbesserung nach Optimierung überprüfen:
# Basisgröße vor Änderungen aufzeichnen
ls -lh output.js # z. B. Vorher: 2,1 MB
# Nach Anwendung der Lösungen neu bündeln und vergleichen
npx react-native bundle --entry-file index.js --bundle-output output.js \
--platform ios --dev false --minify true
ls -lh output.js # z. B. Nachher: 1,6 MB (24% Reduktion)
Häufige Lösungen:
- Vermeide Barrel-Imports (direkt aus der Quelle importieren)
- Entferne unnötige Intl-Polyfills erst nach Überprüfung der Hermes-API- und Methodenabdeckung
- Bewerte Tree Shaking (Expo SDK 52+ experimentelle Entfernung ungenutzter Importe/Exporte oder Re.Pack nur, wenn bereits konfiguriert)
- Aktiviere R8 für Android-nativen Code Shrinking
Hoch: TTI-Optimierung
TTI messen:
- Verwende
react-native-performancefür Marker - Messe nur Kaltstarts (warme/heiße/vorgewärmte ausschließen)
Häufige Lösungen:
- Für React Native 0.78 und älter, deaktiviere die Android-JS-Bundle-Kompression, um Hermes mmap zu ermöglichen
- Verwende native Navigation (react-native-screens)
- Lade häufig verwendete teure Bildschirme vor, bevor zu ihnen navigiert wird
Hoch: Native Leistung
Nativ profilieren:
- iOS: Xcode Instruments → Time Profiler
- Android: Android Studio → CPU Profiler
Häufige Lösungen:
- Verwende Hintergrund-Threads für schwere native Arbeit
- Bevorzuge asynchrone gegenüber synchronen Turbo-Modul-Methoden
- Verwende C++ für plattformübergreifenden leistungskritischen Code
Referenzen
Vollständige Dokumentation mit Codebeispielen in references/:
JavaScript/React (js-*)
| Datei | Auswirkung | Beschreibung |
|---|---|---|
| js-lists-flatlist-flashlist.md | KRITISCH | ScrollView durch virtualisierte Listen ersetzen |
| js-profile-react.md | MITTEL | agent-device react-devtools Profiling |
| js-measure-fps.md | HOCH | FPS-Überwachung und -Messung |
| js-memory-leaks.md | MITTEL | JS-Speicherleck-Suche |
| js-atomic-state.md | HOCH | Jotai/Zustand-Muster |
| js-concurrent-react.md | HOCH | useDeferredValue, useTransition |
| js-react-compiler.md | HOCH | Automatische Memoisierung |
| js-animations-reanimated.md | MITTEL | Reanimated Worklets |
| js-bottomsheet.md | HOCH | Bottom-Sheet-Optimierung |
| js-uncontrolled-components.md | HOCH | TextInput-Optimierung |
Native (native-*)
| Datei | Auswirkung | Beschreibung |
|---|---|---|
| native-turbo-modules.md | HOCH | Schnelle native Module erstellen |
| native-sdks-over-polyfills.md | HOCH | Native vs. JS-Bibliotheken |
| native-measure-tti.md | HOCH | TTI-Messung einrichten |
| native-threading-model.md | HOCH | Turbo Module Threads |
| native-profiling.md | MITTEL | Xcode/Android Studio Profiling |
| native-platform-setup.md | MITTEL | iOS/Android-Tooling-Leitfaden |
| native-view-flattening.md | MITTEL | View-Hierarchie-Debugging |
| native-memory-patterns.md | MITTEL | C++/Swift/Kotlin-Speicher |
| native-memory-leaks.md | MITTEL | Native Speicherleck-Suche |
| native-android-16kb-alignment.md | KRITISCH | Drittanbieter-Bibliotheksausrichtung für Google Play |
Bundling (bundle-*)
| Datei | Auswirkung | Beschreibung |
|---|---|---|
| bundle-barrel-exports.md | KRITISCH | Barrel-Imports vermeiden |
| bundle-analyze-js.md | KRITISCH | JS-Bundle-Visualisierung |
| bundle-tree-shaking.md | HOCH | Tote-Code-Entfernung |
| bundle-analyze-app.md | HOCH | App-Größenanalyse |
| bundle-r8-android.md | HOCH | Android-Code-Shrinking |
| bundle-hermes-mmap.md | HOCH | Bundle-Kompression deaktivieren |
| bundle-native-assets.md | HOCH | Asset-Katalog-Einrichtung |
| bundle-library-size.md | MITTEL | Abhängigkeiten bewerten |
| bundle-code-splitting.md | MITTEL | Sicherheitsvorkehrungen für Remote-Chunk-Laden |
Problem → Skill-Zuordnung
| Problem | Beginne mit |
|---|---|
| App fühlt sich langsam/ruckelig an | js-measure-fps.md → js-profile-react.md |
| Zu viele Re-Renderings | js-profile-react.md → js-react-compiler.md |
| Langsamer Start (TTI) | native-measure-tti.md → bundle-analyze-js.md |
| Große App-Größe | bundle-analyze-app.md → bundle-r8-android.md |
| Speicher wächst | js-memory-leaks.md oder native-memory-leaks.md |
| Animation ruckelt | js-animations-reanimated.md |
| Bottom-Sheet-Ruckeln/Re-Renderings | js-bottomsheet.md → js-animations-reanimated.md |
| List-Scroll-Ruckeln | js-lists-flatlist-flashlist.md |
| TextInput-Verzögerung | js-uncontrolled-components.md |
| Langsames natives Modul | native-turbo-modules.md → native-threading-model.md |
| Ausrichtungsproblem mit nativer Bibliothek | native-android-16kb-alignment.md |
Zuschreibung
Basierend auf „The Ultimate Guide to React Native Optimization“ von Callstack.