Eine realistische Einschätzung von Code-Sharing zwischen Mobile und Web
react-native-web rendert dieselben View-, Text- und ScrollView-Primitives, die auf iOS und Android verwendet werden, als reguläre DOM-Elemente im Browser. Dieser Artikel zeigt, wie diese Übersetzung tatsächlich funktioniert, wo Styling und Plattform-APIs echte Grenzen setzen und wie viel Code am Ende wirklich geteilt landet, sobald Navigation, native Hardware-Zugriffe und Layout-Details ins Spiel kommen.
Inhaltsverzeichnis
- 1. Wie react-native-web die RN-Primitives auf DOM-Elemente abbildet
- 2. Setup in einem bestehenden RN-Projekt: Bundler-Alias und Webpack/Metro-Konfiguration
- 3. Styling-Unterschiede: StyleSheet, Flexbox-Defaults und Media Queries
- 4. Plattform-spezifische APIs: Platform.select und .web.tsx-Dateiendungen
- 5. Navigation: React Navigation im Web-Kontext gegen klassisches Web-Routing
- 6. Grenzen: native APIs ohne Web-Pendant
- 7. Praxisbeispiel: eine geteilte Button-Komponente für beide Plattformen
- 8. Realistische Einschätzung: wie viel Code sich tatsächlich teilen lässt
- 9. Performance und Bundle-Size-Betrachtung für das Web-Ziel
- 10. Zusammenfassung
- 11. FAQ
1. Wie react-native-web die RN-Primitives auf DOM-Elemente abbildet
react-native-web übersetzt die grundlegenden React-Native-Komponenten wie View, Text, ScrollView und Image zur Laufzeit in reguläre DOM-Elemente, meist div, span und img, und übersetzt gleichzeitig das StyleSheet-API in CSS-Klassen, die über eine eigene, hocheffiziente Insertion-Engine ins Dokument geschrieben werden. Für die aufrufende Komponente ändert sich dabei nichts, sie importiert weiterhin dieselben Komponenten aus react-native, nur der Build-Prozess ersetzt das Zielmodul.
Diese Übersetzung funktioniert, weil React Native Primitives von Anfang an bewusst plattformunabhängig als reine Layout- und Darstellungscontainer entworfen wurden, ohne feste Bindung an UIKit oder das Android View System. Genau diese Abstraktion macht react-native-web erst möglich, während eine Bibliothek, die direkt native Views voraussetzt, ohne Web-Fallback nicht automatisch mitübersetzt werden kann.
2. Setup in einem bestehenden RN-Projekt: Bundler-Alias und Webpack/Metro-Konfiguration
In einem bestehenden React-Native-Projekt wird react-native-web meist über eine zusätzliche Webpack- oder Vite-Konfiguration eingebunden, die das Modul react-native per Alias auf react-native-web umleitet, während Metro für die nativen Builds unverändert bleibt. Für React-Native-Projekte, die bereits Expo verwenden, übernimmt der Expo-Webpack-Support diese Umleitung weitgehend automatisch, sobald das Web-Target aktiviert wird.
Wichtig ist, dass Bundle-Splitting nach Plattform sauber konfiguriert wird, damit plattformspezifischer Code, der nur auf iOS oder Android existiert, nicht versehentlich im Web-Bundle landet und dort zur Buildzeit fehlschlägt. Üblich ist eine strikte Trennung über Dateiendungen kombiniert mit einer expliziten Resolver-Reihenfolge, die dem Bundler mitteilt, welche Endung für welches Ziel Priorität hat.
3. Styling-Unterschiede: StyleSheet, Flexbox-Defaults und Media Queries
React Native verwendet standardmäßig flexDirection: column, während CSS im Web standardmäßig row als Flexbox-Richtung annimmt. react-native-web gleicht diesen Unterschied für die eigenen Primitives automatisch aus, aber jeder direkt geschriebene CSS-Code außerhalb von StyleSheet-Objekten muss diesen Unterschied bewusst berücksichtigen, sonst brechen Layouts, die auf Mobile korrekt aussehen, im Web unerwartet um.
Medienabfragen existieren im ursprünglichen React-Native-StyleSheet-Modell nicht, weshalb responsive Layouts fürs Web zusätzliche Werkzeuge wie useWindowDimensions oder eine dedizierte Responsive-Bibliothek brauchen, die zur Laufzeit auf Breakpoints reagiert, statt sich wie im Web auf deklarative CSS-Media-Queries zu verlassen. Das ist einer der Punkte, an denen geteilter Code am ehesten zusätzliche Plattform-Logik braucht.
4. Plattform-spezifische APIs: Platform.select und .web.tsx-Dateiendungen
Für Code, der auf einer Plattform grundlegend anders funktionieren muss, bietet React Native zwei etablierte Mechanismen: Platform.select für kleine, inline verzweigte Werte innerhalb einer Datei, und dateibasierte Plattform-Endungen wie Button.web.tsx und Button.native.tsx für komplett unterschiedliche Implementierungen, die der Bundler automatisch je nach Zielplattform auswählt.
In der Praxis eignet sich Platform.select für punktuelle Unterschiede wie einen leicht abweichenden Schatten-Stil, während dateibasierte Endungen sich für Komponenten lohnen, die auf Web und Mobile grundlegend verschiedene Implementierungen brauchen, etwa eine Kartenansicht, die im Web auf eine JavaScript-Bibliothek und auf Mobile auf ein natives SDK zurückgreift.
5. Navigation: React Navigation im Web-Kontext gegen klassisches Web-Routing
React Navigation unterstützt react-native-web grundsätzlich und übersetzt Navigationsübergänge auf URL-Änderungen über die History-API, wenn ein passender linking-Konfigurationsblock hinterlegt ist. Für einfache Stack-Navigation funktioniert das gut, aber komplexere Web-typische Anforderungen wie tief verschachteltes, SEO-relevantes serverseitiges Routing stoßen an die Grenzen eines primär für native Apps entworfenen Navigationssystems.
Projekte mit hohem Anspruch an klassisches Web-Routing, etwa öffentlich indexierte Marketingseiten, ersetzen die Navigation im Web-Build häufig ganz durch ein dediziertes Web-Framework wie Next.js, während geteilte Inhaltskomponenten weiterhin aus dem gemeinsamen React-Native-Codebestand importiert werden. Die Navigation selbst gehört damit zu den Bereichen, die realistisch eher plattformspezifisch bleiben.
6. Grenzen: native APIs ohne Web-Pendant
Kamera-Zugriff, Bluetooth, native Push-Benachrichtigungen, Biometrie und viele andere native Module haben schlicht kein direktes Web-Äquivalent, weil der Browser entweder gar keinen Zugriff auf die entsprechende Hardware bietet oder ein komplett anderes API-Modell verwendet, etwa die MediaDevices-API des Browsers statt eines nativen Kamera-SDKs. Für solche Fälle bleibt nichts anderes übrig, als eine eigene Web-Implementierung zu schreiben oder das Feature im Web-Build bewusst zu deaktivieren.
Auch Bibliotheken aus dem React-Native-Ökosystem, die selbst kein Web-Target unterstützen, etwa spezialisierte native UI-Komponenten, lassen sich nicht automatisch mitverwenden. Vor der Entscheidung für react-native-web lohnt sich deshalb eine Bestandsaufnahme, welche der bereits eingesetzten Abhängigkeiten überhaupt ein Web-Target mitbringen, statt das erst mitten im Projekt festzustellen.
7. Praxisbeispiel: eine geteilte Button-Komponente für beide Plattformen
Eine gute Kandidatin für echtes Code-Sharing ist eine einfache, präsentationelle Komponente wie ein Button, der nur Text, Farbe und einen Press-Handler braucht, ohne plattformspezifische native Abhängigkeit. Solange ausschließlich React-Native-Primitives verwendet werden, funktioniert dieselbe Datei unverändert auf iOS, Android und im Web-Build über react-native-web.
Das folgende Beispiel zeigt genau eine solche Komponente, die ohne jede plattformspezifische Verzweigung auskommt und trotzdem auf allen drei Zielen identisch dargestellt wird.
import { Pressable, Text, StyleSheet } from "react-native";
type Props = {
label: string;
onPress: () => void;
};
export function SharedButton({ label, onPress }: Props) {
return (
<Pressable style={styles.button} onPress={onPress}>
<Text style={styles.label}>{label}</Text>
</Pressable>
);
}
const styles = StyleSheet.create({
button: {
paddingVertical: 12,
paddingHorizontal: 20,
borderRadius: 8,
backgroundColor: "#4338ca",
},
label: {
color: "#ffffff",
fontWeight: "600",
textAlign: "center",
},
});
8. Realistische Einschätzung: wie viel Code sich tatsächlich teilen lässt
In der Praxis lässt sich vor allem reine Business-Logik, also Validierung, Datenverarbeitung, API-Clients und State-Management, nahezu vollständig teilen, weil diese Ebenen ohnehin unabhängig von plattformspezifischen UI-Details sind. Bei UI-Komponenten sinkt der Anteil geteilten Codes dagegen deutlich, sobald Layout-Feinheiten, Gesten oder plattformtypische Interaktionsmuster ins Spiel kommen, die auf Mobile und im Web unterschiedlich erwartet werden.
Realistische Projekte erreichen häufig eine Code-Sharing-Quote zwischen 60 und 80 Prozent für die Anwendungslogik, aber deutlich weniger für die tatsächlich sichtbare Oberfläche, wo Hover-Zustände, Tastatur-Navigation und Web-typische Layout-Muster eigene Anpassungen brauchen. Wer eine 100-Prozent-Code-Sharing-Quote als Ziel ausgibt, unterschätzt in der Regel, wie unterschiedlich sich Nutzer auf Touchscreens und mit Maus und Tastatur tatsächlich verhalten.
Ein realistischer Fahrplan setzt deshalb von Anfang an unterschiedliche Erwartungen je Ebene: Für Datenmodelle, Validierungsregeln und State-Management lohnt sich striktes Teilen ohne Kompromisse, während für Layout-Feinheiten und Interaktionsmuster bewusst Raum für plattformspezifische Anpassungen eingeplant werden sollte, statt nachträglich um jede kleine Abweichung zu kämpfen. Teams, die diese Erwartung früh im Projekt klären, vermeiden spätere Diskussionen darüber, ob eine Komponente wirklich zu hundert Prozent identisch aussehen muss.
9. Performance und Bundle-Size-Betrachtung für das Web-Ziel
Ein Web-Build über react-native-web bringt zwangsläufig einen gewissen Laufzeit-Overhead mit, weil die StyleSheet-zu-CSS-Übersetzung und die Primitive-Abstraktion zur Laufzeit im Browser passieren, statt bereits zur Buildzeit in reines, minimales CSS umgewandelt zu werden. Für die meisten Anwendungen ist dieser Overhead vernachlässigbar, kann aber bei sehr performance-sensitiven Marketing- oder Landingpages spürbar werden, wo jede Millisekunde Ladezeit zählt.
Bundle-Size lässt sich über konsequentes Code-Splitting je Route und durch Ausschluss nativer, im Web ungenutzter Abhängigkeiten aus dem Web-Bundle deutlich reduzieren. Ein sorgfältig konfigurierter Bundler-Alias, der native-only Pakete im Web-Build gar nicht erst auflöst, verhindert, dass unnötiger nativer Code mit ins Browser-Bundle wandert und die initiale Ladezeit unnötig verlängert.
| Bereich | Anteil geteilten Codes | Typische Einschränkung | Empfehlung |
|---|---|---|---|
| Business-Logik & State | Sehr hoch, meist 80-100% | Kaum plattformspezifisch | Vollständig gemeinsam halten |
| API-Clients & Datenverarbeitung | Sehr hoch | Netzwerk-APIs meist plattformunabhängig | Gemeinsame Module ohne Plattformzweige |
| Präsentationelle UI-Komponenten | Mittel, meist 50-70% | Styling-Details, Interaktionsmuster | Mit Platform.select punktuell anpassen |
| Navigation & Routing | Niedrig | Web-Routing-Anforderungen weichen stark ab | Oft bewusst plattformspezifisch halten |
| Native Hardware-Features | Sehr niedrig bis keine | Kein direktes Web-Äquivalent | Eigene Web-Implementierung oder Feature-Flag |
Mironsoft
React-Native-App-Entwicklung und Magento-Anbindung
Eine mobile App zum Magento-Shop, die wirklich rund läuft?
Wir entwickeln React-Native-Apps, die sauber an die Magento REST- oder GraphQL-API angebunden sind, von der ersten Codezeile bis zur Veröffentlichung im App Store und bei Google Play.
App-Konzeption
Architektur und Feature-Umfang einer Magento-angebundenen App gemeinsam planen.
Magento-API-Integration
Produktkatalog, Warenkorb und Checkout sauber an die Shop-API anbinden.
Store-Veröffentlichung
App Store- und Google-Play-Freigabeprozess ohne Stolperfallen begleiten.
10. Zusammenfassung
React Native Web Code-Sharing: Das Wichtigste auf einen Blick
Funktionsweise
react-native-web übersetzt RN-Primitives zur Laufzeit in DOM-Elemente und StyleSheet-Objekte in CSS-Klassen.
Setup
Bundler-Alias leitet react-native im Web-Build auf react-native-web um, Metro bleibt für native Builds unverändert.
Realistische Quote
Business-Logik lässt sich fast vollständig teilen, UI-Feinheiten und Navigation deutlich weniger.
Grenzen
Native Hardware-Features und plattformspezifische Bibliotheken ohne Web-Target lassen sich nicht automatisch mitverwenden.