Traiter les dossiers natifs comme des résultats de compilation avec Expo Prebuild et CNG
Comment la génération continue de code natif permet à une application Expo d’utiliser des modules natifs personnalisés, des plugins de configuration et des secrets EAS sans avoir à modifier manuellement les dossiers iOS et Android.
Pendant des années, les équipes React Native sur Expo ont dû faire face au même dilemme : dès qu’un projet avait besoin d’un module natif personnalisé, d’audio en arrière-plan ou d’un SDK fournisseur, la solution était expo eject, ce qui faisait que le projet JavaScript bien organisé prenait soudainement en charge les dossiers ios et android complets. Dès lors, l’équipe devait également gérer CocoaPods, modifier build.gradle et déboguer les erreurs Xcode. La génération native continue (CNG) et Expo Prebuild éliminent ce compromis. Ce guide explique comment fonctionne ce modèle, comment les plugins de configuration remplacent les modifications natives manuelles, comment se remettre d’erreurs de compilation Android locales, et comment intégrer des secrets dans les compilations en cloud sans les stocker localement.
Le code natif en tant qu’artefact de compilation
CNG repose sur un principe fondamental : les projets natifs sont générés automatiquement, et non maintenus manuellement.
L’exécution de npx expo prebuild génère les dossiers ios et android à partir d’une seule source fiable, à savoir votre app.json ou app.config.js. Prebuild lit cette configuration, applique les modifications natives qu’elle décrit et produit des projets natifs complets prêts à être compilés.
Puisque ces dossiers peuvent être recréés à tout moment, de nombreuses équipes ajoutent /ios et /android dans le fichier .gitignore. Lorsqu’une dépendance native se retrouve dans un état défectueux, ou lors d’une mise à jour de React Native, on supprime ces dossiers et on les recrée. La question quotidienne passe alors de « Qu’a modifié quelqu’un dans le projet Xcode ? » à « Que déclare la configuration ? ».
Cela établit également la seule règle du modèle : une fois les dossiers natifs générés, il ne faut pas les modifier manuellement. Toute modification effectuée à la main disparaît lors de la prochaine préconstruction. Si vous avez besoin d’un changement, celui-ci doit être exprimé dans la configuration.
Les plugins de configuration remplacent les modifications manuelles des fichiers natifs
Cela soulève une question évidente : comment ajouter des permissions dans le AndroidManifest.xml ou modifier le AppDelegate.mm si les fichiers générés sont interdits de modification ?
Les plugins de configuration en sont la réponse. Un plugin de configuration est une fonction JavaScript qui s’exécute pendant la préconstruction et modifie le projet natif de manière contrôlée et reproductible. Les applications ayant des exigences natives complexes, telles que le traitement en temps réel du langage parlé ou la rendu de modèles 3D, dépendent de bibliothèques nécessitant des intégrations profondes au niveau natif, et ces bibliothèques fournissent généralement leurs propres plugins.
Au lieu d’éditer le code natif, vous listez le plugin et ses options dans app.json. L’exemple ci-dessous utilise expo-build-properties pour définir la valeur compileSdkVersion d’Android à 34, une valeur qui serait normalement contenue dans un fichier Gradle :
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"android": {
"compileSdkVersion": 34
}
}
]
]
}
}
Lors de la prochaine étape de préconstruction, le plugin écrit cette valeur dans le projet Android généré. Comme le changement est déclaré plutôt que mis en œuvre manuellement, il reste inchangé à chaque régénération et est visible lors des revues de code.
Préserver la santé des builds Android locaux
Expo Go est excellent pour la création précoce de prototypes, mais il ne comprend que les modules natifs fournis avec lui. Lorsque vous avez recours à du code natif personnalisé, vous effectuez des tests avec des versions de développement en utilisant npx expo run:android ou npx expo run:ios. Cela est particulièrement important pour les applications qui effectuent de lourds traitements sur le dispositif, comme les fonctionnalités d’IA, où il est nécessaire de voir la véritable performance sur un appareil ou un émulateur.
L’outilchain Android a la réputation de disposer de caches fragiles. Un scénario typique : vous ajoutez une dépendance, et la prochaine compilation locale échoue en raison d’une erreur obscure liée à Java ou Gradle. La cause est généralement des résultats de compilation obsolètes et non votre code.
Une compilation propre est la première chose à essayer. Allez dans le répertoire android généré, exécutez la tâche de nettoyage de Gradle pour supprimer les résultats en cache, puis revenez à la racine du projet et compilez à nouveau :
cd android
./gradlew clean
cd ..
npx expo run:android
Si une simple opération de nettoyage ne suffit pas, CNG propose une solution plus efficace : npx expo prebuild --clean supprime et régénère complètement les dossiers natifs, ce qui est sûr justement parce que rien à l’intérieur n’est géré manuellement. Intégrer ces deux pratiques dans votre routine permet d’éviter de longues sessions de débogage.
Fournir des secrets pour les builds cloud EAS
CNG est particulièrement utile lorsqu’il est combiné à EAS (Expo Application Services) pour les builds cloud.
Prenons l’exemple de la surveillance des erreurs. Les applications en production en ont besoin, et l’intégration de Sentry implique le téléchargement de cartes sources, ce qui nécessite un SENTRY_AUTH_TOKEN. Traditionnellement, ce token devait parvenir à chaque environnement de build tout en restant hors du répertoire, ce qui rendait sa gestion complexe.
Avec CNG et EAS, vous ajoutez le plugin de configuration de Sentry dans app.json sans jamais enregistrer le token. Au lieu de cela, vous l’enregistrez comme variable d’environnement dans EAS à l’aide de la CLI, lui accordant un niveau de visibilité secret et une portée au niveau du projet, de sorte qu’il soit disponible lors des builds mais ne soit pas affiché par la suite. Exécutez la commande une fois, en remplaçant la valeur de remplacement par votre token réel :
eas env:create --name SENTRY_AUTH_TOKEN --value your_token_here --visibility secret --scope projecteas env:create --name SENTRY_AUTH_TOKEN --value your_token_here --visibility secret --scope project
Lors d’un build cloud, EAS exécute la phase pré-build pour générer les projets natifs ; le plugin Sentry lit alors le secret depuis l’environnement, configure le SDK natif et télécharge les cartes sources. Aucun fichier natif ni aucun token n’atteint jamais le contrôle de version. Les paramètres exacts de eas env:create peuvent changer entre les versions de la CLI, il convient donc de consulter la documentation actuelle d’EAS si la commande est rejetée.
Lorsque CNG nécessite une attention particulière
Le modèle est puissant, mais certaines situations exigent une planification préalable :
- Bibliothèques sans plugins. Si un SDK natif ne dispose pas de plugin de configuration, vous devrez peut-être écrire vous-même un petit plugin local plutôt que d’éditer les fichiers générés.
- Projets existants en état avancé. Les applications contenant des années de code natif modifié manuellement ne peuvent pas simplement supprimer leurs dossiers ; la migration consiste à transférer chaque personnalisation dans la configuration en premier.
- Discipline d’équipe. CNG ne fonctionne que si tout le monde considère
iosetandroidcomme des éléments réutilisables. Une simple modification rapide dans Xcode sera perdue silencieusement lors de la prochaine génération.
En résumé
Expo Prebuild et CNG rendent les applications React Native complexes de niveau production beaucoup plus accessibles en faisant des couches natives des éléments réutilisables :
- Déclarez les exigences natives dans
app.jsonouapp.config.jset laissez Prebuild gérer le reste.
prebuild --clean lorsque les builds locaux échouent de manière mystérieuse.SENTRY_AUTH_TOKEN dans les variables d’environnement EAS, jamais dans le répertoire de dépôt.Avec les projets natifs réduits à des résultats de build, l’attention de l’équipe se reporte sur le code React Native, les interfaces fluides et les fonctionnalités du produit.
Lectures complémentaires
- Mise en place d’un module Turbo intégré de bout en bout avec React Native Codegen — Définissez une spécification typée, exécutez le codegen, et implémentez un module Turbo sur iOS et Android en utilisant des méthodes synchrones, Promise, callback et émetteur d’événements.
- Changement de thème permanent dans React Native avec Context et Hooks — Créez un outil de changement de thème pour React Native en utilisant Context, useState et useEffect : navigation par onglets, sélection du thème, persistance via AsyncStorage et protection contre les chargements en cours au démarrage.