Mon premier module Open Source pour React Native

Souhaitant développer une application mobile pour une webradio avec comme cible Android et iOS, mon choix s’est porté sur React Native qui fait beaucoup parler de lui ses derniers temps et que nous souhaitons utiliser à la place de Titanium.

Ayant fait le tour des modules disponibles pour jouer un flux audio, je me suis aperçu qu’il n’y en avait aucun cross-platform. J’ai donc décidé de créer mon propre module React Native. Cet article retrace ce parcours et les problèmes rencontrés lors du développement du module react-native-audio-streaming.

Ci-dessous un aperçu de la première version du module réalisé.

Demo iOSDemo android

Les recherches initiales

Le point de départ est bien souvent la question « Quelqu’un l’a-t-il déjà développé ? ». C’est encore plus d’actualité sur un environnement aussi dynamique que React Native où de nombreuses librairies sont créées chaque jour.

Ce qui m’amène sur l’excellent dépôt de @jhabdas et ses slides sur la création d’une application iOS pour la webradio Lumpen.

iOS

La partie iOS du module est donc déjà bien avancée. L’ensemble du code est sous licence MIT, je peux donc le récupérer. Il manque par contre la gestion des metadatas envoyés par le protocole Shoutcast (logiciel open source utilisé par de nombreuses webradio).

Heureusement pour moi, une personne a déjà rajouté ce support dans son fork et je peux donc le récupérer.

Android

Pour cette plateforme, le module react-native-android-audio-streaming-aac dispose déjà des fonctionnalités avec le support des métadonnées Shoutcast. Il utilise la librairie aacDecoder qui ne semble plus maintenue mais l’implémentation était déjà réalisée et j’ai donc gardé cette librairie, une mise à jour la remplacera probablement par l’ExoPlayer.

Le module React Native

Trouver un nom

Ce module va permettre de faire du streaming audio, tous les modules étant préfixés par « react-native », je pars donc sur le nom « react-native-audio-streaming ». Après une rapide recherche sur npm, déception, le nom est déjà pris 😢 (pour information, ce module n’existait pas encore lors de la réalisation de l’application radio, qui bénéficiera de ce module plus tard). Peut être est-il possible de contribuer à ce module au lieu de créer le mien ?

Le package npm ne possède pas de lien vers ses sources et aucune trace du dépôt dans ceux de l’auteur. Je le contacte donc pour en savoir plus sur l’état de son module.

Le développeur, Matteo Mazzarolo me répond qu’il ne souhaite plus le maintenir et qu’il a donc supprimé son module, tout en me proposant de transférer sa possession du package sur npm. Super !

Initialiser le projet

Ayant récupéré les différentes librairies et la possession du nom que je veux utiliser, il faut maintenant démarrer le développement du module.

La première chose à faire est de choisir une licence, pour ce faire les sites opensource.org et choosealicense.com permettent de se faire une idée rapidement. Je sélectionne donc la licence MIT qui possède le plus de liberté de partage du code.

Pour le code, je souhaite avoir une application d’exemple dans mon dépôt, après quelques recherches sur les bonnes manières d’initialiser un module, je trouve la commande officielle react-native new-library mais elle est peu documentée, ainsi qu’un autre outil en cli : react-native-create-library.

La commande officielle nécessite un projet déjà créé et inclut une version ancienne de React Native. Je choisis donc la deuxième qui me crée les 3 projets de librairies associés (iOS, Android et même Windows !).

$ react-native-create-library ReactNativeAudioStreaming
…
$ tree -d ./

├── android
│   └── src
│       └── main
│           └── java
│               └── com
│                   └── reactlibrary

├── ios
│   └── RNReactNativeAudioStreaming.xcodeproj

└── windows
    └── RNReactNativeAudioStreaming
        └── RNReactNativeAudioStreaming
            └── Properties

Ensuite, j’initialise le module et renseigne les informations de celui-ci :

npm init

Puis je créé l’application d’exemple et installe les dépendances :

mkdir Example && cd Example
react-native init
npm install ../

La suite consiste à lier notre application d’exemple avec notre package tout neuf, si l’on suit la manière de développement des packages NPM, cela consiste à utiliser npm link pour créer un lien symbolique vers notre module. Hélas, ils ne sont pas résolus par le packager de React Native (problème bientôt résolu), et je dois donc copier coller mes changements pour les garder synchronisés avec la librairie… Une alternative créé par la communauté est l’utilitaire wml, mais je ne l’ai pas testé.

Développement et uniformisation des APIs

Étant donné que la majeure partie du module est native, nous ne pouvons pas bénéficier du live/hot reload proposé par le compilateur, il faut donc relancer l’application à chaque modification via Xcode ou Android Studio. Toutefois, sur Android, nous pouvons profiter du build incrémental proposé par Gradle.

Je ne vais pas détailler le code nécessaire pour exposer les fonctions ou envoyer des événements au runtime JS car cela est déjà bien détaillé dans la documentation officielle :

La principale difficulté est de savoir se débrouiller avec les trois langages, l’Objective-C, le Java et le Javascript. Il vaut mieux s’isoler au maximum dans un environnement que de s’éparpiller à vouloir implémenter chaque fonctionnalité en parallèle.

De plus, il faut garder en tête les limitations de chaque plateforme. Par exemple, sur iOS, nous disposons des événements « Remote control » et de l’interface native lorsque l’application est en background, par contre sur Android, nous devons implémenter cette interface à la main avec une notification active.

Pour lier le code natif de notre module avec l’application d’exemple, nous devons les lier à la compilation avec la commande react-native link react-native-audio-streaming.

Publication

NPM

N’ayant jamais publié de package sur NPM avant, j’ai cherché le meilleur workflow disponible. La commande npm publish est simple d’utilisation mais il faut modifier la version à la main, créer la release et par conséquent il y a une forte probabilité d’erreur.

Le package np propose un workflow plus complet qui vérifie l’installation des dépendances, le code non commité, va lancer les tests et mettre à jour automatiquement la version dans le package.json.

Open source

Tous les projets nécessitent un minimum d’informations pour le démarrage ou l’installation. Le README est la première chose qu’un utilisateur va lire en arrivant sur votre librairie, il nécessite donc une attention particulière.

Le plus important est d’expliquer comment le module peut être installé et configuré. Pour React Native par exemple, cela revient à proposer la commande npm install avec le nom du module, puis à ajouter les éléments à modifier pour lier le code natif du module à l’application.

Comme introduction, personnellement j’apprécie une rapide liste des fonctionnalités de la librairie, avec, si nécessaire, plus de détails par la suite : notamment pour ce module, deux gifs montrant les différents comportement sur chaque plateforme (réalisé avec Giphy capture sur macOS).

N’hésitez pas à rajouter du code d’exemple pour guider le développeur sur l’utilisation de votre librairie. Dans mon cas, j’ai copié/collé le code principal de l’application d’exemple qui inclut le composant de la librairie.

L’autre partie importante est le suivi des mises à jour via un CHANGELOG qui permet de suivre l’évolution du projet mais surtout d’informer lors de dépréciations d’API. Je conseille fortement le site keepachangelog.com pour plus d’informations à ce sujet.

Conclusion

Je me suis aperçu que l’open source est un travail de tous les jours, je n’ai pour l’instant qu’un seul contributeur mais qui apporte sa vision et son code et il faut être prêt à en discuter et à prendre des décisions en commun. Je n’ose imaginer le temps nécessaire pour maintenir et faire évoluer des projets très populaires…

Excepté quelques ennuis pour gérer les dépendances natives, je trouve la création d’un module natif agréable et plus facile qu’avec Titanium (système de build plus complexe, SDK en global, peu de de documentations…). Les contributeurs sont aussi beaucoup plus nombreux avec plus de 2000 résultats sur snpm pour le mot clé « react-native » contre 1432 pour « titanium » (statistiques gitt.io) alors qu’il est plus ancien.

PS: Ce module a été utilisé dans l’application « La Cave Webradio » disponible pour Android et iOS !

Nos formations sur le sujet

  • React Native

    Développez des applications mobiles natives et cross-platform pour iOS et Android grâce à React Native.

blog comments powered by Disqus