React Native
,Firebase
Optimisez votre application avec Firebase Crashlytics
Intégrer crashlytics de firebase à votre application React Native.
Murat
09 décembre 2021
Le “crash reporting” vous connaissez ? C’est une des notions les plus importantes afin d’assurer la bonne qualité de votre application.
Les bugs et crashes qui appairaissent dans votre application une fois déployée, peuvent être très difficile à taquer. Vous ne serez sûrement pas en contact avec les utilisateurs afins qu’ils puissent vous détailler ce qu’il s’est passé. Et encore pire, l’utilisateur vous laissera sûrement une mauvaise note.
Dans ce tutoriel, nous allons voir comment intégrer le module crashlytics à votre applicatin react native.
Ce tutoriel nécessite que vous ayez complété notre première partie sur l’initialisation de firebase avec React Native.
Installation
Le module @react-native-firebase/crashlytics propose des fonctionnalités utiles pour les développeurs.
Créer le projet dans la console Firebase
Allez sur la console Firebase, assurez-vous que votre projet est créé, sinon suivez l’article précédent.
Intégrer @react-native-firebase/crashlytics
Exécutez dans un terminal dans votre projet :
yarn add @react-native-firebase/crashlyticscd ios/ && pod install
Pour la partie android, dans android/build.gradle
:
// ..buildscript {// ..dependencies {// ..classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'}// ..}
Puis build à nouveau le projet avec :
npx react-native run-android
Tester votre configuration
Afin d’être sûr que le paramétrage fonctionne, créez d’abord un fichier firebase.json
à la racine de votre projet, en y ajoutant :
{"react-native": {"crashlytics_auto_collection_enabled": true,"crashlytics_debug_enabled": true, // c'est temporaire, on va remettre à false plus tard"crashlytics_javascript_exception_handler_chaining_enabled": false}}
crashlytics_debug_enabled
permet de dire à Crashlytics d’également tracker les bugs en mode debug. C’est important pour notre premier test.
Ensuite, soit lors d’un clic de bouton, soit au chargement d’un screen, insérez ce bout de code :
import crashlytics from '@react-native-firebase/crashlytics';// ..crashlytics().crash();
Allez ensuite sur la console Firebase, puis attendez 1 ou 2 minutes pour voir apparaître votre erreur :
Testez la manip’ sur les 2 simulateurs iOS et android pour être sûr que tout fonctionne.
Maintenant, on peut passer aux cas pratiques !
Intégration d’un ErrorBoundary
Explication
Crashlytics va maintenant attraper les erreurs qui proviennent dans votre application, et vous les lister dans la console. Mais comme vous le savez, le code react native
est compilé en natif, donc vous perdez votre code javascript lors de la release.
Donc vos stack d’erreurs ne seront pas très lisible.
Exemple de stack d’erreur reporté par crashlytics
.
Fatal Exception: java.lang.ClassCastException: com.facebook.react.bridge.ReadableNativeMap cannot be cast to java.lang.Stringat com.facebook.react.bridge.ReadableNativeArray.getString(ReadableNativeArray.java:102)at com.facebook.react.bridge.JavaMethodWrapper$5.extractArgument(JavaMethodWrapper.java:73)at com.facebook.react.bridge.JavaMethodWrapper$5.extractArgument(JavaMethodWrapper.java:69)at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:356)at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)at com.facebook.react.bridge.queue.NativeRunnable.run(NativeRunnable.java)
La méthode pour récupérer l’erreur javascript est la suivante :
crashlytics().recordError(error);
ErrorBoundary
L’explication étant maintenant terminée, passons à la bonne pratique. Le composant ErrorBoundary permet de rattraper les erreurs qui se produisent dans le code javascript, et de montrer une vue plus propre à l’utilisateur, au lieu de faire cracher l’application.
Comme par exemple :
Nous allons mettre en place ce composant, et envoyer les erreurs à Crashlytics à ce moment.
Dans component/ErrorBoundary.js
:
import crashlytics from '@react-native-firebase/crashlytics';import { node } from 'prop-types';import React, { Component } from 'react';import { SafeAreaView, Text, View } from 'react-native';import RNRestart from 'react-native-restart'import Button from '~/components/common/Button';import t from '~/configs/i18n';import styles from './styles';class ErrorBoundary extends Component {constructor(props) {super(props);this.state = {};}static getDerivedStateFromError() {return { hasError: true };}componentDidCatch(error, errorInfo) {if(errorInfo && errorInfo.componentStack) {crashlytics().log(errorInfo.componentStack);}crashlytics().recordError(error, error.message ? error.message : undefined);}onRestart() {RNRestart.Restart();};render() {const { hasError } = this.state;const { children } = this.props;if (hasError) {return (<SafeAreaView style={{ flex: 1 }}><View style={styles.container}><View style={styles.content}><Text style={{ width: '100%', }}>500</Text><Text style={{ fontSize: 32 }}>{t('label.error')}</Text><Text style={{ marginVertical: 10, lineHeight: 23, fontWeight: '500' }}>{t('error.description')}</Text><ButtononPress={() => this.onRestart()}>{t('action.backToLogin')}</Button></View></View></SafeAreaView>);}return children;}}ErrorBoundary.propTypes = {children: node,};ErrorBoundary.defaultProps = {children: null,};export default ErrorBoundary;
Puis dans App.js
, entourez votre application avec ce composant :
return (<ErrorBoundary><Provider store={store}><PersistGate loading={null} persistor={persistor}>{storybookActive ? <StorybookUIRoot /> : <Router />}</PersistGate></Provider></ErrorBoundary>);
Voila ! Maintenant à chaque crash, nous allons envoyer les informations js à la console Crashlytics
de Firebase
. Ce que j’aime bien mettre en place, c’est le rechargement de l’application lors du clic sur le bouton, grâce à la dépendance react-native-restart. C’est optionnel bien sûr.
Loggez encore plus d’information
Grâce à l’étape précédente, vous aurez la stacktrace javascript. Mais c’est toujours mieux de rajouter plus d’info (bien sûr, avec parcimonie).
Pour cela 2 méthodes :
crashlytics().log(errorInfo.componentStack); //celle-là permet de logger une activité sur crashlyticscrashlytics().setAttribute(attribute, value); //celle-là permet de mettre un attribut
J’utilise la 2ème méthode pour savoir sur quelle page l’utilisateur se trouvait avant le grand crash.
Si vous utilisez @react-navigation/native :
<NavigationContainertheme={AppTheme}ref={navigationRef}onReady={() => {routeNameRef.current = navigationRef.current.getCurrentRoute().name;crashlytics().setAttribute("screen", routeNameRef.current);}}onStateChange={() => {const previousRouteName = routeNameRef.current;const currentRouteName = navigationRef.current.getCurrentRoute().name;if (previousRouteName !== currentRouteName) {crashlytics().setAttribute("screen", currentRouteName);}routeNameRef.current = currentRouteName;}}>
Conclusion
Et voila ! Ça fait pas mal d’information quand même. Maintenant j’espère que vous allez pouvoir débugger vos applications plus facilement. Ne tracker pas des informations susceptibles d’identifier vos utilisateurs (#rgpd).
Technologies dans cet article ...
Mobile
React Native
Firebase
D'autres articles dans la même catégorie...
#Javascript
#Cordova
#React Native
#HTML
#Développement
#Application mobile
Développement mobile : Natif vs. hybride.
Stéphane
28 décembre 2023
#Android Natif
#React Native
#Firebase
#Cordova
#Application mobile
#Développement
Bonnes pratiques pour le développement d'apps mobiles
Farid
11 avril 2023
#React Native
#Firebase
Comment déployer des apps iOS avec Apple Ad-Hoc
Murat
03 avril 2023