React Native - Anwendung und Kritik

Bei der Auswahl dieser Sprache wird meistens erwartet, dass die Entwicklung einer Anwendung für zwei Plattformen die Hälfte der Zeit in Anspruch nimmt als die Entwicklung von zwei Anwendungen. Am Ende stellt sich jedoch heraus, dass die Entwicklung aufgrund der Schwierigkeiten, die unter der äußeren Brillanz und dem Marketing verborgen sind, genauso viel, wenn nicht sogar mehr kostet. Wir werden über einige der ähnlichen Schwierigkeiten sprechen, auf die wir in den letzten Monaten der Arbeit mit React Native gestoßen sind.


React Native passt Javascript für die mobile Entwicklung an. Dies wird durch die Tatsache erreicht, dass er mehrere Kollektoren zum Erstellen von Projekten verwendet - Metro Bundler, der den JS-Code interpretiert und die Ressourcen und den Kollektor des Zielsystems darstellt. In unserem Fall war es ein Gradle für Android. Theoretisch sollte die React Native-Anwendung ganz einfach starten. Der reaktionsnative Befehl run-android aktiviert den Metro Bundler und erstellt die Anwendung für alle angeschlossenen Android-Geräte und Emulatoren.


In Wirklichkeit stellte sich heraus, dass es bereits in diesem Stadium Schwierigkeiten gibt. In unserem Projekt wurde ständig der Fehler "JS-Bundle kann nicht heruntergeladen werden" angezeigt, sodass der Bundler den Code nicht in den nativen Code übersetzen konnte. Wie sich später herausstellte, aufgrund der Tatsache, dass es nicht gestartet wurde. StackOverflow bestätigte die Vermutung und schlug vor, Bundler in einem separaten Thread mit dem Befehl react-native start auszuführen. Auf diese Weise können Sie den Bundler nur neu starten, wenn sich package.json geändert hat, da die Prozedur die Entwicklung nicht wesentlich verlangsamt.


Package.json ist eine Datei, die eine Reihe externer Module für die Anwendung enthält. Bei npmjs.com gibt es eine große Anzahl verschiedener Bibliotheken für React Native, die die Funktionalität erweitern und die Entwicklung vereinfachen. Viele Bibliotheken (z. B. Firebase) verwenden native Funktionen und müssen daher direkt mit nativem Code verknüpft werden. Verwenden Sie dazu den Befehl react-native link <Bibliotheksname>, mit dem diese Beziehungen mit nativem Code konfiguriert werden sollen.


Aufgrund der Tatsache, dass alle Bibliotheken zu unterschiedlichen Zeiten geschrieben werden, verwenden sie unterschiedliche Versionen des SDK und erfordern einen anderen Ansatz. Manchmal kommt es vor, dass Bibliotheken nicht miteinander kompatibel sind oder die neueste Version der Bibliothek experimentell ist und die Entwickler selbst empfehlen, ein Downgrade auf die vorletzte durchzuführen. Sehr oft konfiguriert Link nicht alle erforderlichen Abhängigkeiten. Für die oben genannte Firebase müssen Sie also viele zusätzliche Bibliotheken im nativen Code hinzufügen, verschiedene externe Repositorys verbinden und mainApplication.java ändern (und dies gilt nur für Android!). Für Firebase gibt es eine ziemlich verständliche Anweisung zum Ausführen dieser Aktionen, für andere Bibliotheken ist sie jedoch nicht immer vorhanden.


Nachdem die Verbindungen mit dem nativen Code konfiguriert wurden, können Sie das Projekt in der Hoffnung erstellen, dass die verbundene Bibliothek funktioniert. Beachten Sie beim Zusammenbau, dass Sie bei einem Fehler sicherstellen sollten, dass er genau aufgrund Ihrer Aktionen und nicht aufgrund eines Kollektorfehlers aufgetreten ist. Um vollständige Sicherheit zu gewährleisten, sollten Sie die folgende Abfolge von Aktionen ausführen:


rmdir node_modules /s /q && npm cache clean - force && npm i 

Dieser Befehl löscht den Ordner node_modules und lädt ihn erneut. Dies ist eine der längsten Aufgaben, daher lohnt es sich, sie äußerst selten zu verwenden. Bei einigen Projekten können node_modules bis zu mehreren Gigabyte auf der Festplatte belegen. Daher dauert die Neuinstallation einige Zeit.


 rmdir android/app/build /s /q 

Während der Entwicklung wurde festgestellt, dass der häufig erfolglose Build eine Folge der Tatsache ist, dass der Collector keinen Ordner aus dem Debug-Verzeichnis erstellen (oder löschen) kann. Diese Aktion löst das Problem, dass durch Reagieren der Ordner nicht selbst gelöscht werden kann. Gleichzeitig dauert das erneute Generieren von Dateien für diesen Ordner von Grund auf länger.


 react-native start-reset-cache 

Starten Sie den Metro Bundler. Diese Registerkarte sollte während des gesamten Debugging-Vorgangs geöffnet bleiben. Wenn ein Fehler auftritt, wird möglicherweise das Fehlerprotokoll hier angezeigt. Wenn ein Fehler auftritt, wird dieser Prozess höchstwahrscheinlich beendet und muss erneut gestartet werden.


 react-native run-android 

Installieren Sie die Anwendung auf einem angeschlossenen Gerät oder Emulator. Die meisten Build-Fehler treten hier auf, und einige von ihnen sind verständlich, andere sind jedoch ziemlich irrational und werden durch einen Neustart des gesamten Prozesses "geheilt".


Stellen Sie sich den Erstellungsprozess mit einer Folge von Befehlen für ein Projekt vor (bereits Realm, Redux, React-Navigation, etwa zehn weitere Bibliotheken), nachdem Sie Firebase verbunden haben.


 react-native start react-native run-android >>    debug react-native run-android >> , metro bundler  react-native start react-native run-android >>    debug react-native run-android >>  !  metro bundler ,   JS-   react-native start >>   restart         -  

Unnötig zu sagen, es dauert wirklich lange? Und dies ist kein einmaliger Vorgang: Zum beschriebenen Zeitpunkt war dieser Vorgang nach fast jeder Änderung des Programmcodes erforderlich. Mit jeder neuen Bibliothek wird das Projekt immer weniger stabil, und dieser Prozess kann sich ändern, meistens zum Schlechten. Das Debuggen einer Anwendung ist eine der wichtigsten Funktionen für einen Entwickler, und in diesem Fall nimmt die Geschwindigkeit erheblich ab.


Apropos Debuggen. Der React Native-Debugger hat nicht nur Probleme beim Start. Die Korrektur von Fehlern, die als Ergebnis des Tests festgestellt wurden, ist ebenfalls ein ziemlich schmerzhafter Prozess. In React-Native wird der JS-Code in Native-Code übersetzt, während der Übersetzung jedoch verschleiert. Wenn Sie also keine Fehler wie "Nullzeigerausnahme in zzz.yyy ()" sehen möchten, müssen Sie den integrierten Debugger verwenden. Sie können nicht nur Ausnahmen in logcat lesen. Bei einem Fehler zeigt der Debugger einen roten "Bildschirm des Todes" mit seiner Beschreibung an, der mehr oder weniger auf den Korrekturpfad zusteuert. Aber es gibt Probleme mit diesem Teil.


Nun, wenn der Fehler so aussieht:



Es ist wirklich klar, was hier passiert - anstelle des erwarteten Array-Objekts ist this.state.noteArray.map undefiniert, was den berüchtigten TypeError verursacht. Sie können das Problem beheben, indem Sie in app.js: 14 den Wert dieser Variablen vor der Verwendung überprüfen.


Schlimmer noch, wenn der Fehler so aussieht:



Also:



Oder so:



Bilder wurden aus dem Internet aufgenommen, aber wir haben sie live gesehen. Und trotz der Tatsache, dass sie zur Laufzeit angezeigt werden, ist dieser Fehler nicht darauf zurückzuführen, dass in Ihrem Code etwas falsch gemacht wurde. Dies kann daran liegen, dass Sie die Bibliothek falsch installiert haben oder dass Ihre Importe inkompatible Abhängigkeiten aufweisen oder dass im nativen Code ein Fehler aufgetreten ist und React versucht, den Fehler abzufangen. Jeder Fehler ist individuell und wird sehr unterschiedlich gelöst. Es ist gut, dass es StackOverflow und zumindest eine Art Debugging-Modus gibt.


Schlimmer noch, wenn ein Fehler beim Debuggen nicht reproduziert wird. Diese Situation ist aufgetreten, als wir versucht haben, eine Anwendung mit einer neuen Version von React mit Unterstützung für die x64-Architektur für Android zu erstellen. Bei der Installation einer Anwendung mit einem Debugger funktioniert alles einwandfrei. Sobald wir den Tester auf dem Telefon erstellen, funktioniert alles nicht mehr und bricht ab, sobald es um die Interaktion mit der Datenbank geht. Um das Nicht-Debuggen in Eile zu debuggen, verwenden wir Konsolennachrichten, die in diesem Fall die Komponente "toastAndroid reagieren" waren. Diese Komponente zeigt beim Erreichen einer bestimmten Codezeile einen kurzen Text an. Methodisch, vorzugsweise durch Teilen des Codes in zwei Hälften, lokalisieren wir die Funktion, in der der Fehler auftritt, und stellen fest, dass die Object.assign-Methode ({}, item) in der neuen Version von React nicht funktioniert. Es war ein Glück, dass Sie diese Funktion durch ein kürzeres {... Element} ersetzen konnten, während die Funktionalität der Anwendung beibehalten wurde. Die Suche nach diesem Fehler kostete jedoch etwa ein Dutzend Arbeitsstunden.


Nach einer kleinen Studie wurde auf der Suche nach Gründen durchgeführt. Wie sich herausstellte, verwendet React Native verschiedene Javascript-Engines zum Interpretieren von JS-Code in Debug- und Produktionsversionen: zum Debuggen der Chrome JS-Engine und in JavaScriptCore. Ja, React Native übersetzt JavaScript nicht in nativen Code, sondern interpretiert es während der Ausführung. Gleichzeitig arbeitet die Debugging-Engine viel stabiler, und daher schleichen sich zunehmend Fehler in die Produktion ein. In diesem Artikel wird beispielsweise gezeigt, wie die Datumsformatierung unter verschiedenen Bedingungen funktioniert. Zurück zum Fehler: Es stellte sich heraus, dass die Web-Engine für die Produktionsproduktion nach dem Aktualisieren der React Native-Version die Unterstützung für Object.assign () verlor. Die Debugging-Engine blieb jedoch dieselbe.


Die vielleicht schlechteste Option ist der Fall, wenn die Anwendung an zufälligen Stellen unterbrochen wird, nur in der Produktionsversion und ohne Protokolle von React Native. Beispiel: Nach der Installation der Release-Version der Anwendung auf dem Telefon funktioniert sie "eine Weile" und wird dann "ohne Fehler oder Warnung in einem zufälligen Moment ausgeschaltet". Darüber hinaus wird der Fehler nicht auf allen Geräten reproduziert. Am Ende gelang es uns durch Versuch und Irrtum (und durch die Feststellung, dass die oben genannten Firebase Crashlytics nicht die entsprechenden Fehler senden), die Fallprotokolle abzufangen, die so aussahen:



Dieser Text gilt nicht einmal für unsere Bewerbung, er wurde nicht einmal rot markiert. Aber nachdem wir es bekommen und in die Foren gegangen waren, stellten wir fest, dass die neue Version von React Native kaputt ist. Und der vorherige war kaputt. Auf dem offiziellen Issue Tracker bestand der Fehler "Android stürzt ab: Signal 11 (SIGSEGV)" zwei Monate lang, und zu unserem Glück zwei Tage bevor wir dorthin gingen (!) Wurde eine experimentelle Lösung vorgeschlagen, die den Fehler behebt.


Es ist ironisch, dass einige Entwickler, die sich mit Android Studio auseinandersetzen mussten, ratlos waren, dass die IDE Optionen wie Build / Clean-Projekt oder Datei / Ungültigmachen von Caches hat. Dies ist erforderlich, um das abnormale Verhalten von Gradle durch falsche Fehlermeldungen und Warnungen sowie durch Synchronisationsfehler zu beseitigen. Die Entwickler fragten: "Warum sollten wir die Arbeit für unsere IDE erledigen? In solchen Situationen sollten diese Befehle automatisch ausgeführt werden." Und sie können verstanden werden, aber gleichzeitig erledigen moderne IDEs die schwierige Arbeit hinter den Kulissen. Und diese Entwickler haben einfach nicht mit React Native gearbeitet.


Alle oben genannten Fälle sind Einzelfälle, die in den letzten Wochen aufgetreten sind. Hier beschreiben wir nicht die Komplexität der Ausführung von Anwendungen mit Expo, da der Codestil in babel / eslint festgelegt ist. Wir schimpfen nicht mit Javascript für übermäßige Flexibilität. Wir sagen nicht, wie das Debuggen aufgrund der Redux / Realm-Verknüpfung bei einem der Projekte fast vollständig verloren gegangen ist. Angesichts der beschriebenen Schwierigkeiten bei Support und Entwicklung und der Tatsache, dass bei zwei Systemen alles mit zwei multipliziert wird, lohnt es sich zu überlegen, ob React Native wirklich rentabel ist. Nachdem wir unser drittes Projekt in dieser Sprache abgeschlossen hatten, entschieden wir uns nicht. Was denkst du?

Source: https://habr.com/ru/post/de468901/


All Articles