Migrer un module Expo
Migrer le côté Swift d'un module Expo existant sans modifier son API JS observable. Traiter la surface JS/TypeScript actuelle et les tests comme le contrat de compatibilité. Laisser Kotlin sur le DSL 1.0 sauf si l'utilisateur élargit explicitement la tâche.
Prérequis
Les macros de l'API Expo Modules 2.0 nécessitent expo 57.0.7 ou plus récent. Avant de modifier, vérifier la version installée de la cible (expo dans package.json/lockfile, ou npm ls expo). Si elle est plus ancienne, s'arrêter et demander à l'utilisateur de mettre à niveau d'abord ; ne pas tenter la migration contre une version non prise en charge. C'est un plancher, pas une garantie : la surface macro et core exacte varie toujours dans 57.x, donc l'étape 2 doit toujours vérifier la source extraite.
Références
- Lire
references/migration-map.mdavant de modifier la source. Elle contient les mappages 1.0-to-2.0, les pièges sémantiques, et les règles de mode mixte. - Lire
references/example.mdpour une démonstration complète avant/après d'un module en mode mixte jusqu'à une migration complète. La consulter quand on a besoin de voir comment les règles par membre se composent. - Lire
references/compatibility.mdquand la version ou la brancheexpo-modules-coreextraite n'est pas connue pour supporter chaque macro demandée. Elle explique comment vérifier la surface compile-time et runtime réelle au lieu de deviner à partir d'un numéro de SDK.
Flux de travail
1. Établir le contrat
Inspecter les instructions du repository et l'arborescence avant de modifier. Localiser les classes de module Swift, les records, les objets partagés, les vues natives, les bindings JS/TS, les tests, l'app exemple, le podspec, et expo-modules-core installé ou extrait.
Inventorier chaque élément exporté avant de le réécrire :
- noms JS du module et des objets partagés
- noms de fonction, arité, labels, valeurs par défaut, nullabilité, comportement sync/async, erreurs, et sémantique de queue
- noms de propriété, mutabilité, et comportement de cache constant
- noms de wire d'événement et formes de payload
- noms de champ record, valeurs par défaut, requérabilité, et nullabilité
- constructeurs d'objet partagé et placement instance/static
- hooks de cycle de vie et vues
Utiliser les déclarations TypeScript et les sites d'appel JS pour résoudre l'ambiguïté. Ne pas silencieusement « améliorer » la requérabilité, renommer un événement, ou changer le comportement sync pendant une migration syntaxique.
2. Vérifier la surface 2.0 disponible
Inspecter les déclarations de macro et les hooks core correspondants dans la dépendance réellement utilisée par la cible. Ne pas supposer que tous les éléments du design 2.0 sont présents parce qu'une macro compile.
Classifier chaque élément 1.0 comme :
- Migrer : sa macro et le support runtime core requis existent.
- Garder dans le DSL : le mode mixte le préserve en sécurité, ou 2.0 n'a pas d'équivalent.
- Bloqué : la migration altèrerait le contrat JS ou nécessite un support runtime indisponible.
Préférer un résultat en mode mixte incrémental au code généré spéculatif. Garder definition() pour tout élément DSL restant ; le supprimer seulement s'il est vide et que le nom de module résolu est préservé par @ExpoModule.
3. Appliquer la migration
Migrer un groupe sémantique à la fois : noms de module, fonctions, propriétés/constantes, événements, objets partagés, puis records. Garder le diff étroit.
Suivre ces invariants :
- Préserver explicitement chaque nom JS-visible existant quand les règles de nommage Swift ou les défauts de macro diffèrent.
- Garder le comportement optionnel/défaut original. Un champ record 1.0 optionnel ne doit pas devenir requis simplement parce que 2.0 peut exprimer des champs requis.
- Ne pas migrer les surcharges de même nom JS à moins que la macro extraite ne les groupe et dispatche.
- Ne pas migrer les fonctions DSL épinglées à queue tel quel ; restructurer vers Swift Concurrency ou dispatcher vers la queue originale via une continuation, selon les règles async-function dans
references/migration-map.md. - Ne pas migrer les vues, unions, événements synchrones, ou fonctions statiques d'objet partagé sans support vérifié.
- Ne pas changer Kotlin, les wrappers JS, ou les fichiers
.d.tspublics sauf si l'utilisateur a demandé un changement d'API.
Après chaque groupe, rechercher les anciennes entrées DSL et les sites d'appel qui auraient dû se déplacer. Éviter le formatage large ou le nettoyage non lié.
Quand un équivalent 2.0 manque ou un groupe échoue
Quand l'étape 2 a classifié un élément comme Bloqué, ou qu'un groupe migré échoue à compiler ou casse le contrat, ne pas le forcer. S'arrêter sur ce groupe et :
-
Demander à l'utilisateur comment procéder pour cet élément, avec deux options :
- Co-exister : garder l'élément dans le DSL
definition()1.0 à côté du@ExpoModulemigré (mode mixte) et continuer avec les autres groupes. - Revenir : annuler les modifications du groupe, le laisser intact sur 1.0, et passer au suivant.
Par défaut, préférer la co-existence quand le mode mixte est vérifié sûr, car il préserve le plus de progrès. Revenir quand le changement partiellement appliqué a laissé le module dans un état ne compilant pas et ne peut pas être sauvegardé de manière incrémentale.
- Co-exister : garder l'élément dans le DSL
-
Ouvrir un issue de suivi sur
expo/exponotant la fonctionnalité que 2.0 ne couvre pas encore, de sorte que l'écart soit enregistré plutôt que silencieusement contourné. Utilisergh issue create --repo expo/expoet confirmer avec l'utilisateur avant de poster (selon les conventions du repo, ne pas poster de commentaires visibles sans approbation). Inclure :- le membre 1.0 et son contrat JS
- la macro spécifique ou le hook core manquant (citer l'écart de preuve de
references/compatibility.md) - la version/branche
expo-modules-coreextraite
Référencer l'issue dans le handoff pour que l'entrée DSL restante soit traçable à une limitation connue.
Continuer avec les groupes qui migrent sans problème ; un membre bloqué ne bloque pas le reste.
4. Vérifier le comportement
Exécuter les vérifications les plus étroites en premier, puis la surface d'intégration réelle :
- Compiler ou vérifier les types du module Apple contre la cible
expo-modules-core. - Exécuter les tests unitaires natifs et les tests JS/TS.
- Compiler et lancer l'app exemple quand le repository en fournit une.
- Comparer la surface exportée finale avec l'inventaire de l'étape 1.
- Rechercher les entrées
Namepérimées, les entrées migréesFunction/Property/Constant/Events, les anciens appelssendEvent,@Field, et les registrations dupliquées.
Les tests d'expansion seuls sont insuffisants : le code macro généré peut sembler correct tout en échouant contre les symboles core mal appairés. Si les dépendances ont changé ou les flags du plugin macro manquent, réinstaller les dépendances JS le cas échéant, exécuter le flux de travail d'installation CocoaPods du repository, et redémarrer Xcode avant de diagnostiquer les défaillances de communication du plugin.
Handoff
Signaler :
- quels membres ont passé à 2.0
- quels membres restent intentionnellement dans le DSL 1.0 et pourquoi
- tous les choix sensibles à la compatibilité, spécialement les noms d'événement, la requérabilité record, les constantes, et les queues
- les commandes exécutées et toute vérification non complétée