Intégrer des vues React Native dans votre projet Capacitor

Pourquoi et quand intégrer l’IA dans une application Capacitor ?

Accès à des API natives spécifiques

Bien que Capacitor dispose d’un vaste écosystème de plugins permettant d’accéder à de nombreuses fonctionnalités natives, il existe encore des niches où l’écosystème React Native offre des capacités uniques.

Certains composants UI spécialisés ou certaines fonctionnalités spécifiques à un appareil peuvent avoir des implémentations React Native matures mais des équivalents Capacitor limités ou inexistants, l’intégration AR/VR dans notre cas en est un exemple concret.

Il est important de noter que ces cas sont relativement rares, car l’écosystème Capacitor, soutenu à la fois par l’équipe Ionic et les contributeurs de la communauté, couvre un large éventail de fonctionnalités natives.

Avant de décider d’intégrer React Native, faites des recherches approfondies sur l’écosystème de plugins Capacitor, car la fonctionnalité dont vous avez besoin peut déjà être disponible sans nécessiter la complexité supplémentaire de l’intégration de React Native.

Migration progressive de Capacitor vers React-Native

Si vous prévoyez une migration de Capacitor vers React Native, une approche progressive est souvent la stratégie la plus judicieuse.

L’intégration de vues React Native dans votre app Capacitor existante peut servir de pont pendant cette transition. Cette méthode permet aux équipes de tirer parti des atouts des deux frameworks tout en modifiant progressivement l’architecture de leur application.

Optimisation des performances

La différence de performance entre React Native et les vues web (comme celles utilisées dans Capacitor) est souvent surestimée et dépend fortement du cas d’utilisation spécifique. Dans de nombreux scénarios, des vues web bien optimisées peuvent être aussi performantes que les composants React Native.

Cependant, pour certains éléments ou animations complexes de l’interface utilisateur, React Native peut offrir des performances plus fluides grâce à son accès direct aux composants natifs de l’interface utilisateur.

Il est essentiel d’effectuer des analyses comparatives et des tests dans votre cas d’utilisation spécifique plutôt que de supposer que React Native sera toujours plus rapide.

La décision d’utiliser des vues React Native doit être basée sur des freins spécifiques à la performance identifiés dans votre application Capacitor, et non sur des hypothèses générales. Prenez en compte des facteurs tels que la complexité de votre interface utilisateur, le type d’interactions (par exemple, des gestes ou des animations complexes) et les appareils cibles lorsque vous évaluez les avantages potentiels en termes de performances.

Intégration des vues React Native dans votre application Capacitor

Plongeons-nous maintenant dans les principales étapes de l’intégration des vues React Native dans votre application Capacitor.

Attention :

Les écosystèmes React Native et Capacitor évoluent rapidement. Vous pouvez rencontrer des variations, des obstacles ou des erreurs en fonction de vos versions spécifiques et des dépendances du projet. En outre, ce guide se concentre sur l’intégration d’une application React Native « brute », par opposition à une application gérée par Expo. Bien que les principes généraux soient similaires, les spécificités peuvent différer légèrement.

En tant que guide utile tout au long de ce processus, gardez cette section pertinente de la documentation React Native ouverte dans un onglet du navigateur pour pouvoir vous y référer facilement.

Installation des dépendances

NPM

Tout d’abord, dans votre projet Capacitor, vous voudrez ajouter quelques dépendances et devDependencies npm:

npm i -S react react-native
npm i -D @react-native/metro-config

et optionellement (mais recommandé) :

npm i -D @react-native/babel-preset @react-native/eslint-config @react-native/typescript-config

Android

Ne rentrons pas trop dans les détails ici, pour cela vous pouvez consulter le commit que nous avons ajouté dans le repo de démonstration, et consulter la doc react native, mais en résumé, vous aurez besoin de :

  • ajouter le plugin react-native gradle dans les dépendances de votre buildscript dans le build.gradle racine
  • ajouter les dépendances react-native et hermes dans le fichier app/build.gradle
  • éditer settings.gradle pour activer l’autolinking et configurer le plugin react native gradle
  • éditer le nœud de l’application AndroidManifest.xml, en définissant usesCleartextTraffic à true si vous ciblez l’API >= 28. Sans cela, vous ne pourrez pas exécuter les vues react-native en debug.
<application android:usesCleartextTraffic="true" tools:targetApi="28" >
<!-- ... -->
</application>

iOS

La principale chose à faire pour iOS est de mettre à jour le Podfile pour inclure les dépendances et les actions post-installation pour faire fonctionner react-native. Cela permettra au moins de faire fonctionner l’application en mode debug.

Pour créer une archive (une release build) dans laquelle vous pouvez intégrer les vues RN, vous devez ajouter une build phase :

  • Allez dans l’onglet « Build Phases » dans Xcode
  • Ajoutez une nouvelle phase de construction, en cliquant sur « + » puis en sélectionnant « New Run Script Phase »
  • Placez-la de façon à ce qu’elle soit exécutée après la phase appelée « Copy Bundle Resources »

Voici le contenu du script que vous souhaitez exécuter à cette étape :

set -e

WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
REACT_NATIVE_XCODE="../node_modules/react-native/scripts/react-native-xcode.sh"

/bin/sh -c "$WITH_ENVIRONMENT $REACT_NATIVE_XCODE"

N’oubliez pas de lancer pod install dans votre dossier ios, et d’ouvrir android studio pour effectuer une synchronisation gradle afin que toutes les dépendances que vous avez déclarées pour android et iOS soient correctement téléchargées.

Avec les dépendances nécessaires en place, l’étape suivante consiste à incorporer le code source de l’application React Native dans votre projet Capacitor. Nous allons ensuite mettre en place les composants nécessaires pour charger de manière transparente ces vues React Native à partir de votre code TypeScript (ou JavaScript).

Copier les sources et les fichiers de configuration de React Native

Cette étape est simple : copiez les fichiers sources de votre application React Native existante dans votre projet Capacitor. Si vous partez de zéro, créez ces fichiers directement dans votre projet Capacitor.

Voici, au minimum, les fichiers dont vous aurez besoin :

  • App.tsx (ou App.jsx) : Ce fichier hébergera votre composant React Native principal.
  • index.js : Situé à la racine de votre projet, ce fichier enregistrera votre composant React Native principal. C’est le point d’entrée à votre code React Native.
  • metro.config.js : ce fichier de configuration permet l’utilisation du mode debug basé sur un serveur de développement basé sur metro bundler

N’oubliez pas d’inclure tous les composants supplémentaires, les fichiers de style, les modules ou les assets nécessaires au bon fonctionnement de votre application React Native.

Une bonne pratique consiste à conserver index.js au niveau de la racine. Vous pouvez organiser le reste de votre code source React Native selon une structure adaptée à votre projet.

Pour une démonstration détaillée, consultez notre repo de démonstration. L’historique des commits fournit un guide étape par étape.

Place au code

Une fois vos sources React Native intégrées, nous devons établir un pont permettant à votre application Capacitor de charger ces vues et d’interagir avec elles. Le système de plugins de Capacitor rend ce processus particulièrement simple.

Voici un aperçu des étapes à suivre :

Android

Créez une nouvelle activity : Elle servira de wrapper pour vos vues React Native. Lorsqu’elle est instanciée à partir d’une méthode de plugin, elle charge et affiche votre contenu React Native.

Créer un fichier de plugin : ce fichier sert d’intermédiaire entre votre application Capacitor et le code natif Android. Définissez les méthodes du plugin que vos vues web peuvent appeler et les événements que le plugin peut émettre pour renvoyer des données à votre application web.

iOS

Créez un nouveau ViewController : Il sera responsable de l’instanciation et de la gestion de vos vues React Native.

Créer un fichier de plugin : Comme pour Android, ce fichier gère la communication entre Capacitor et le code natif iOS.

Mettre à jour le Storyboard : Faites référence au ViewController nouvellement créé dans votre Storyboard principal pour vous assurer qu’il est intégré dans le schéma de navigation de votre application.

TypeScript

Instancier votre plugin grâce aux API de Capacitor afin que nous puissions appeler ses méthodes natives depuis notre code JS/TS :

Créez un index.ts dans les sources de votre projet (peut-être dans un dossier « rn/plugin » par exemple)

Enregistrer le plugin avec la méthode registerPlugin de Capacitor

Important:

Un exemple de code pour l’activité Android et le ViewController et les plugins iOS est disponible dans notre repo de démonstration :

Appeler la méthode du plugin depuis l’application

Une fois que les plugins sont prêts, vous pouvez importer le plugin dans vos vues web et appeler ses méthodes.

import RN from 'path/to/rn/plugin';

...

async openRnView(): Promise<void> {
  await RN.openView();
}

et voilà ! Il ne vous reste plus qu’à builder vos sources, et à vous assurer de lancer:

  • npx cap sync
  • npx react-native start pour lancer le bundler metro
  • dans un autre terminal, vous pouvez ensuite lancer npx react-native run-android et/ou npx react-native run-ios pour installer et lancer l’application sur votre device/émulateur.
    • Ce dernier point est important, car en procédant ainsi, l’application connaîtra automatiquement l’URL du serveur métro qui tourne sur votre machine. Si vous exécutez les applications depuis XCode ou Android Studio comme vous le feriez généralement avec une application Capacitor, les vues web fonctionneront mais l’application ne sera pas en mesure de charger les vues RN depuis le serveur metro.

Limites et réserves potentielles de l’intégration de React Native avec Capacitor

L’intégration des vues React Native dans une application Capacitor, bien qu’offrant des avantages uniques, s’accompagne de son propre lot de défis. Ces limites peuvent aller de la complexité du développement, à des impacts sur la performance en passant par des problèmes de maintenance à long terme. Avant d’adopter cette approche, il est essentiel de comprendre ces inconvénients potentiels :

Complexité accrue :

  • La gestion de deux frameworks complique le développement et le debug.
  • Risque de conflits de dépendances
  • Processus de build et structuration du code plus complexes

Surcharge de performance :

  • Taille plus importante de l’application et temps de démarrage potentiellement plus long
  • Augmentation potentielle de l’utilisation mémoire

Courbe d’apprentissage :

  • Les développeurs doivent maîtriser à la fois Capacitor et React Native.
  • Le debug dans deux écosystèmes peut être plus difficile.

Ressources limitées de la communauté :

  • Moins d’exemples et de solutions pour cette intégration spécifique
  • Risque de problèmes inattendus en raison de la configuration unique.

Considérations relatives à la maintenance

  • Maintien à jour et compatibilité des deux frameworks
  • Processus de tests plus complexes
  • Difficultés potentielles pour maintenir une UI/UX cohérente

Conclusion

L’intégration de vues React Native dans une appli Capacitor offre une solution unique aux développeurs qui cherchent à tirer parti de fonctionnalités natives spécifiques tout en conservant les avantages du développement basé sur le web. Cette approche, bien que puissante, s’accompagne de son propre ensemble de défis et de considérations.