React Native - Application et critique

Le plus souvent, lors du choix de ce langage, le développement d'une application pour deux plates-formes devrait prendre la moitié du temps que le développement de deux applications. Mais au final, il s'avère que le développement prend autant, sinon plus, à cause des difficultés cachées sous l'éclat extérieur et le marketing. Nous parlerons de certaines des difficultés similaires que nous avons rencontrées au cours des derniers mois de travail avec React Native.


React Native adapte Javascript pour le développement mobile. Ceci est réalisé par le fait qu'il utilise plusieurs collecteurs pour construire des projets - Metro Bundler, qui interprète le code JS et représente les ressources et le collecteur du système cible. Dans notre cas, c'était un gradle pour Android. En théorie, l'application React Native devrait démarrer tout simplement. La commande react-native run-android active Metro Bundler et crée l'application pour tous les appareils et émulateurs Android connectés.


En réalité, il s'est avéré que même à ce stade, il y a des difficultés. Une erreur «Impossible de télécharger le bundle JS» est constamment apparue sur notre projet, ce qui signifie que le bundler n'a pas pu traduire le code en natif. Comme il s'est avéré plus tard, car il n'a pas commencé. StackOverflow a confirmé la conjecture et a suggéré que vous devez exécuter bundler dans un thread séparé en utilisant la commande start native. Cela vous permet de redémarrer bundler uniquement si package.json a changé, car la procédure ne ralentit pas beaucoup le développement.


Package.json est un fichier contenant un ensemble de modules externes pour l'application. Sur npmjs.com, il existe un grand nombre de bibliothèques différentes pour React Native, étendant les fonctionnalités et simplifiant le développement. De nombreuses bibliothèques (par exemple, Firebase) utilisent des fonctions natives et doivent donc être associées directement au code natif. Pour ce faire, utilisez la commande react-native link <library-name>, qui doit configurer ces relations avec le code natif.


Étant donné que toutes les bibliothèques sont écrites à des moments différents, elles utilisent différentes versions du SDK et nécessitent une approche différente. Il arrive parfois que les bibliothèques soient incompatibles entre elles, ou que la dernière version de la bibliothèque soit expérimentale, et les développeurs eux-mêmes conseillent de rétrograder vers l'avant-dernière. Très souvent, le lien ne configure pas toutes les dépendances requises. Donc, pour la base de feu susmentionnée, vous devez ajouter de nombreuses bibliothèques supplémentaires en code natif, connecter divers référentiels externes, modifier mainApplication.java (et cela n'est valable que pour Android!). Pour Firebase, il existe une instruction assez compréhensible pour effectuer ces actions, mais pour d'autres bibliothèques, elle n'est pas toujours présente.


Une fois les connexions avec le code natif configurées, vous pouvez créer le projet dans l'espoir que la bibliothèque connectée fonctionnera. Lors de l'assemblage, il convient de se rappeler que si vous obtenez une erreur, vous devez vous assurer qu'elle s'est produite précisément à cause de vos actions, et non à cause d'une erreur de collecteur. Pour une confiance totale, vous devez effectuer la séquence d'actions suivante:


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

Cette commande supprimera le dossier node_modules puis le rechargera. C'est l'une des tâches les plus longues, il vaut donc la peine de l'utiliser extrêmement rarement. Sur certains projets, node_modules peut occuper jusqu'à plusieurs gigaoctets sur le disque dur, et donc la réinstallation prendra du temps.


 rmdir android/app/build /s /q 

Pendant le développement, il a été remarqué que la construction souvent infructueuse est une conséquence du fait que le collecteur ne peut pas créer (ou supprimer) un dossier à partir du répertoire de débogage. Cette action résout le problème selon lequel React ne peut pas supprimer le dossier par lui-même. Mais en même temps, générer à nouveau des fichiers pour ce dossier prendra du temps supplémentaire.


 react-native start-reset-cache 

Lancez Metro Bundler. Cet onglet doit rester ouvert tout au long du processus de débogage. Si une erreur se produit, le journal des erreurs peut apparaître ici. Très probablement, si une erreur se produit, ce processus se terminera et devra être redémarré à nouveau.


 react-native run-android 

Installez l'application sur un appareil ou un émulateur connecté. La plupart des erreurs de build se produisent ici, et certaines sont compréhensibles, mais certaines sont tout à fait irrationnelles et sont "corrigées" en redémarrant l'ensemble du processus.


Imaginez le processus de construction avec une séquence de commandes pour un projet (ayant déjà realm, redux, react-navigation, une dizaine de bibliothèques supplémentaires) après avoir connecté Firebase.


 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         -  

Inutile de dire que cela prend vraiment du temps? Et ce n'est pas un processus unique: au moment décrit, cette procédure était requise après presque chaque modification du code du programme. Avec chaque nouvelle bibliothèque, le projet devient de moins en moins stable, et ce processus peut changer, le plus souvent pour le pire. Le débogage d'une application est l'une des fonctions les plus importantes pour un développeur, et dans ce cas, sa vitesse diminue considérablement.


En parlant de débogage. Le débogueur React Native a non seulement des problèmes de lancement. La correction des erreurs trouvées à la suite du test est également un processus assez douloureux. Dans react-native, le code JS est traduit en code natif, mais est obscurci lors de la traduction. Donc, si vous ne voulez pas voir des erreurs comme "exception de pointeur nul dans zzz.yyy ()", alors vous devez utiliser le débogueur intégré, vous ne pouvez pas simplement lire les exceptions dans logcat. En cas d'erreur, le débogueur affiche un "écran de mort" rouge avec sa description, poussant plus ou moins vers la voie de la correction. Mais il y a des problèmes avec cette partie.


Eh bien, lorsque l'erreur ressemble à ceci:



Il est vraiment clair ce qui se passe ici - au lieu de l'objet tableau attendu, this.state.noteArray.map n'est pas défini, ce qui provoque la fameuse TypeError. Vous pouvez le corriger en accédant à app.js: 14 et en vérifiant la valeur de cette variable avant utilisation.


Pire encore lorsque l'erreur ressemble à ceci:



Donc:



Ou alors:



Les images ont été prises sur Internet, mais nous les avons vues en direct. Et malgré le fait qu'ils soient affichés au moment de l'exécution, cette erreur n'est pas due au fait que quelque chose a été mal fait dans votre code. Cela peut être dû au fait que vous avez mal installé la bibliothèque, ou si vos importations ont des dépendances incompatibles, ou que quelque chose s'est mal passé dans le code natif, et React essaie de détecter l'erreur. Chaque erreur est individuelle et est résolue très différemment. C'est bien qu'il y ait StackOverflow et au moins une sorte de mode de débogage.


Pire encore, lorsqu'une erreur n'est pas reproduite dans le débogage. Nous avons rencontré cette situation lors de la tentative de création d'une application avec une nouvelle version de React avec prise en charge de l'architecture x64 pour Android. Lors de l'installation d'une application avec un débogueur, tout fonctionne bien. Mais dès que nous construisons le testeur sur le téléphone, tout cesse de fonctionner et se casse dès qu'il s'agit d'interagir avec la base de données. Pour déboguer le non-débogage à la hâte, nous utilisons des messages de console, qui dans ce cas étaient le composant react toastAndroid. Ce composant affiche un court texte lorsque vous atteignez une certaine ligne de code. Méthodiquement, en divisant de préférence le code en deux, nous localisons la fonction dans laquelle l'erreur se produit et découvrons que la méthode Object.assign ({}, item) ne fonctionne pas dans la nouvelle version de React. Il a eu la chance de pouvoir remplacer cette fonction par un {... item} plus court tout en conservant la fonctionnalité de l'application, mais la recherche de cette erreur a coûté environ une douzaine d'heures de travail.


Après une petite étude a été menée à la recherche de raisons. Il s'est avéré que React Native utilise différents moteurs Javascript pour interpréter le code JS dans les versions de débogage et de production: pour le débogage du moteur Chrome JS et dans JavaScriptCore. Oui, React Native ne traduit pas JavaScript en code natif, mais l'interprète lors de son exécution. Dans le même temps, le moteur de débogage fonctionne beaucoup plus stable et, par conséquent, les bogues se faufilent de plus en plus en production. Par exemple, cet article montre comment le formatage de la date fonctionne dans différentes conditions. Revenant à l'erreur: il s'est avéré qu'après la mise à jour de la version React Native, le moteur web de production production a perdu le support d'Object.assign (). Mais le moteur de débogage est resté le même.


La pire option est peut-être le cas lorsque l'application se casse à des endroits aléatoires, uniquement dans la version de production et sans aucun journal de React Native. Exemple: après avoir installé la version finale de l'application sur le téléphone, cela "fonctionne pendant un certain temps", puis "s'éteint sans erreur ni avertissement à un moment aléatoire". De plus, l'erreur n'est pas reproduite sur tous les appareils. Au final, par essais et erreurs (et en détectant que le Firebase Crashlytics susmentionné n'envoie pas les erreurs correspondantes), nous avons réussi à attraper les journaux de chute qui ressemblaient à ceci:



Ce texte ne s'applique même pas à notre application, il n'était même pas marqué en rouge. Mais après l'avoir obtenu et être allé sur les forums, nous avons constaté que la nouvelle version de React Native était cassée. Et le précédent était cassé. Sur le Issue Tracker officiel, l'erreur "Android se bloque: signal 11 (SIGSEGV)" existait depuis deux mois, et à notre chance deux jours avant de nous y rendre (!) Une solution expérimentale a été proposée pour corriger l'erreur.


Il est ironique que certains développeurs qui ont dû faire face à Android Studio ne comprennent pas que l'IDE a des options comme construire / nettoyer le projet ou classer / invalider les caches. Cela est nécessaire pour se débarrasser du comportement anormal de gradle, des faux messages d'erreur et des avertissements, des erreurs de synchronisation. Les développeurs ont demandé: "pourquoi devrions-nous faire le travail pour notre IDE, dans de telles situations, ces commandes devraient être exécutées automatiquement." Et ils peuvent être compris, mais en même temps, les IDE modernes font tout le travail difficile dans les coulisses. Et ces développeurs n'ont tout simplement pas travaillé avec React Native.


Tous ces cas sont des cas isolés survenus au cours des dernières semaines. Ici, nous ne décrivons pas la complexité de l'exécution des applications avec Expo, avec la définition du style de code dans babel / eslint, nous ne grondons pas Javascript pour une flexibilité excessive, nous ne disons pas comment le débogage en raison de la liaison redux / realm a été presque complètement perdu sur l'un des projets. Compte tenu des difficultés décrites de support et de développement et du fait que pour deux systèmes, tout se multiplie par deux, cela vaut-il la peine de se demander si React Native est vraiment rentable? Après avoir terminé notre troisième projet dans cette langue, nous avons décidé de ne pas le faire. Qu'en penses-tu?

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


All Articles