SPM: modularisation de projet pour augmenter la vitesse de construction

Bonjour, Habr! Je m'appelle Eric Basargin et je suis développeur iOS chez Surf .



Sur un grand projet, nous avons rencontré une vitesse de construction faible - de trois minutes ou plus. Habituellement, dans de tels cas, les studios pratiquent la modularisation des projets afin de ne pas travailler avec d'énormes monolithes. Chez Surf, nous avons décidé d'expérimenter et de modulariser le projet à l'aide du Swift Package Manager, le gestionnaire de dépendances d'Apple.



Nous parlerons des résultats dans un autre article, mais maintenant nous allons répondre aux principales questions: pourquoi tout cela est-il nécessaire, pourquoi nous avons choisi SPM et comment nous avons fait les premiers pas.







Pourquoi SPM



La réponse est simple - c'est natif et nouveau. Il ne crée pas de frais généraux xcworkspace comme les Cocoapods, par exemple. De plus, SPM est un projet open-source qui se développe activement. Apple et la communauté corrigent des bugs, corrigent des vulnérabilités, se mettent à jour pour suivre Swift.



Est-ce que cela accélÚre la construction du projet



ThĂ©oriquement, l'assemblage va s'accĂ©lĂ©rer du fait mĂȘme de la division de l'application en modules - frameworks. Cela signifie que chaque module ne sera construit que lorsque des modifications y auront Ă©tĂ© apportĂ©es. Mais il ne sera possible de s'affirmer avec certitude qu'Ă  la fin de l'expĂ©rience.



Remarque: L'efficacité de la modularisation dépend directement de la division correcte du projet en modules.



Comment faire un partitionnement efficace



La méthode de partitionnement dépend de l'architecture choisie, du type d'application, de sa taille et des plans de développement ultérieur. Par conséquent, je vais parler de trois rÚgles que nous essayons de respecter lors du fractionnement.



Partagez des fonctionnalités génériques. Chaque module est responsable d'une catégorie, par exemple:



  • CommonAssets - un ensemble de vos actifs et une interface publique pour y accĂ©der. Il est gĂ©nĂ©ralement gĂ©nĂ©rĂ© Ă  l'aide de SwiftGen.
  • CommonExtensions - un ensemble d'extensions, par exemple Foundation, UIKit, des dĂ©pendances supplĂ©mentaires.


Flux d'application sĂ©parĂ©s. ConsidĂ©rez une structure arborescente, oĂč MainFlow est le flux principal de l'application. Disons que nous avons une application de nouvelles.



  • NewFlow - Ă©crans de nouvelles et aperçu des nouvelles spĂ©cifiques.
  • FavoritesFlow — .
  • SettingsFlow — , , . .


reusable :



  • CommonUIComponents — , UI-. .
  • UI . , , , . .




Disons que nous avons un flux spécifique et que nous voulons y ajouter de nouvelles fonctions. Si le composant sera réutilisé ou si cela est théoriquement possible à l'avenir, il est préférable de le déplacer dans un module séparé ou un analogue de CommonUIComponents. Dans d'autres cas, vous pouvez laisser le composant local.



Cette approche résout le problÚme des composants manquants. Cela se produit dans les grands projets, et si le composant n'est pas documenté, son support et son débogage deviendront par la suite non rentables.



Créer un projet avec SPM



Envisagez de créer un projet de test trivial. J'utilise un projet d'application multiplateforme sur SwiftUI. La plate-forme et l'interface n'ont pas d'importance ici.



Remarque: pour créer rapidement une application multiplateforme, vous avez besoin de XCode 12.2 beta. Créons un



projet et voyons ce qui suit:







Créons maintenant le premier module commun:



  • ajoutez le dossier Frameworks sans crĂ©er de rĂ©pertoire;
  • crĂ©er un package SPM Common.






  • Ajoutez les plates-formes prises en charge au fichier Package.swift. Nous l'avonsplatforms: [.iOS(.v14), .macOS(.v10_15)]






  • Maintenant, nous ajoutons notre module Ă  chaque cible. Nous avons ce SPMExampleProject pour iOS et SPMExampleProject pour macOS.






Remarque: il suffit de connecter uniquement les modules racine aux cibles. Ils ne sont pas ajoutés en tant que sous-modules.



La connexion est terminĂ©e. Il ne vous reste plus qu'Ă  configurer un module avec une interface publique - et voilĂ , le premier module est prĂȘt.



Comment ajouter une dépendance pour un package SPM local



Ajoutons le package AdditionalInfo - en tant que Common, mais sans l'ajouter aux cibles. Modifions maintenant le Package.swift du package Common.







Vous n'avez rien d'autre Ă  ajouter. Peut ĂȘtre utilisĂ©.



Un exemple proche de la réalité



Connectons SwiftGen à notre projet de test et ajoutons le module Palette - il sera chargé d'accéder à la palette de couleurs approuvée par le concepteur.



  1. Créez un nouveau module racine en suivant les instructions ci-dessus.

  2. Ajoutez-y les répertoires racine Scripts et Templates.

  3. Ajoutez le fichier Palette.xcassets Ă  la racine du module et notez tous les jeux de couleurs.

  4. Ajoutez un fichier Palette.swift vide Ă  Sources / Palette.

  5. Ajoutez le modĂšle palette.stencil au dossier ModĂšles .

  6. Vous devez maintenant enregistrer le fichier de configuration pour SwiftGen. Pour ce faire, ajoutez le fichier swiftgen.yml dans le dossier Scripts et Ă©crivez ce qui suit:



xcassets:
  inputs:
    - ${SRCROOT}/Palette/Sources/Palette/Palette.xcassets
  outputs:
    - templatePath: ${SRCROOT}/Palette/Templates/palette.stencil
      params:
        bundle: .module
        publicAccess: true
      output: ${SRCROOT}/Palette/Sources/Palette/Palette.swift




L'apparence finale du



module Palette Nous avons configuré le module Palette . Nous devons maintenant configurer le lancement de SwiftGen pour que la palette soit générée au début de la construction. Pour ce faire, accédez à la configuration de chaque cible et créez une nouvelle phase de construction - appelons-la Générateur de palettes. N'oubliez pas de déplacer cette phase de construction à la position la plus élevée possible.



Maintenant, nous Ă©crivons l'appel pour SwiftGen:



cd ${SRCROOT}/Palette
/usr/bin/xcrun --sdk macosx swift run -c release swiftgen config run --config ./Scripts/swiftgen.yml


Remarque: /usr/bin/xcrun --sdk macosxest un préfixe trÚs important. Sans cela, la construction générera une erreur: "impossible de charger la bibliothÚque standard pour la cible 'x86_64-apple-macosx10.15".





Exemple d'appel pour SwiftGen



Done - les couleurs sont accessibles comme ceci:

Palette.myGreen(Type de couleur dans SwiftUI) et PaletteCore.myGreen(UIColor / NSColor).



Roches sous-marines



Je vais énumérer ce que nous avons rencontré.



  • .
  • SwiftLint & SwiftGen SPM. yml.
  • Cocoapods. — , SPM . SPM Cocoapods - : «MergeSwiftModule failed with a nonzero exit code». , .
  • SPM . -L$(BUILD_DIR).


SPM — Bundler?



Dans ce dossier, je propose de rĂȘver et de discuter dans les commentaires. Le sujet doit ĂȘtre bien Ă©tudiĂ©, mais il semble trĂšs intĂ©ressant. Soit dit en passant, il y a dĂ©jĂ  un assez proche intĂ©ressant article sur les avantages et les inconvĂ©nients de SPM.



SPM permet d'appeler swift run en ajoutant Package.swift à la racine de votre projet. Qu'est-ce que ça nous donne? Par exemple, vous pouvez appeler fastlane ou swiftlint. Exemple d'appel:



swift run swiftlint --autocorrect.



All Articles