SPM:项目模块化以提高构建速度

哈Ha!我叫Eric Basargin,我是Surf的iOS开发人员



在一个大型项目中,我们遇到了较低的构建速度-从三分钟或更长时间开始。通常,在这种情况下,工作室会对项目进行模块化,以免使用庞大的整体。Surf的我们决定使用Swift软件包管理器(Apple的依赖项管理器)对项目进行实验和模块化。



我们将在另一篇文章中讨论结果,但是现在我们将回答主要问题:为什么需要所有这些,为什么选择SPM以及如何采取第一步。







为什么选择SPM



答案很简单-它是本地的和新的。例如,它不会像Cocoapods那样产生xcworkspace开销。另外,SPM是一个正在积极开发的开源项目苹果和社区正在修复错误,修复漏洞,更新以遵循Swift。



它会使项目建设更快吗



从理论上讲,由于将应用程序划分为模块(框架)这一事实,因此组装速度将会提高。这意味着只有在对其进行更改后才能构建每个模块。但是,只有在实验结束时才可以肯定地断言。



注意:模块化的有效性直接取决于项目是否正确划分为模块。



如何进行有效的分区



分区方法取决于所选的体系结构,应用程序的类型,其大小和进一步开发的计划。因此,我将讨论拆分时我们要遵循的三个规则。



共享通用功能。每个模块负责一个类别,例如:



  • CommonAssets-您的资产的集合以及用于访问它们的公共接口。它通常使用SwiftGen生成。
  • CommonExtensions-一组扩展,例如Foundation,UIKit和其他依赖项。


单独的应用程序流。考虑一个树结构,其中MainFlow是应用程序的主要流程。假设我们有一个新闻应用程序。



  • NewFlow-新闻屏幕和特定新闻概述。
  • FavoritesFlow — .
  • SettingsFlow — , , . .


reusable :



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




假设我们有一个特定的流程,我们想为其添加新功能。如果该组件将被重用,或者在理论上将来有可能,则最好将其移至单独的模块或CommonUIComponents的类似物中。在其他情况下,您可以将组件保留在本地。



这种方法解决了缺少组件的问题。这在大型项目中会发生,并且如果未记录该组件,则其维护和调试将随后无利可图。



使用SPM创建项目



考虑创建一个琐碎的测试项目。我正在SwiftUI上使用Multiplatform App项目。平台和界面在这里无关紧要。



注意:要快速创建Multiplatform App,您需要XCode 12.2 beta。 让我们创建一个



项目并查看以下内容:







现在让我们创建第一个Common模块:



  • 添加Frameworks文件夹而不创建目录;
  • 创建一个SPM包Common。






  • 将支持的平台添加到Package.swift文件。我们有它platforms: [.iOS(.v14), .macOS(.v10_15)]






  • 现在,我们将模块添加到每个目标。我们有适用于iOS的SPMExampleProject和适用于macOS的SPMExampleProject。






注意:仅将根模块连接到目标就足够了。它们不会添加为子模块。



连接完成。现在,您要做的就是配置一个带有公共接口的模块-瞧,第一个模块已经准备就绪。



如何为本地SPM包添加依赖项



让我们添加AdditionalInfo包-作为Common,但不将其添加到目标中。现在,让我们更改Common包的Package.swift。







您无需添加其他任何内容。可以使用。



一个接近现实的例子



让我们将SwiftGen连接到我们的测试项目并添加Palette模块-它将负责访问设计者认可的调色板。



  1. 按照上面的说明创建一个新的根模块。

  2. 向其中添加脚本和模板根目录。

  3. 将Palette.xcassets文件添加到模块根目录并写下所有颜色集。

  4. 将一个空的Palette.swift文件添加到Sources / Palette。

  5. Palette.stencil模板添加到Templates文件夹中

  6. 现在您需要注册SwiftGen的配置文件。为此,将swiftgen.yml文件添加到Scripts文件夹,并在其中写入以下内容:



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




Palette



模块的最终外观我们已经配置了Palette模块。现在,您需要配置SwiftGen的启动,以便在构建开始时生成调色板。为此,请转到每个目标的配置并创建一个新的构建阶段-我们将其称为Palette generator。不要忘记将构建阶段移到最高位置。



现在我们编写对SwiftGen的调用:



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


注意:/usr/bin/xcrun --sdk macosx是非常重要的前缀。没有它,构建将生成错误:“无法为目标'x86_64-apple-macosx10.15加载标准库”。





SwiftGen



完成的示例调用-可以按以下方式访问

Palette.myGreen颜色(SwiftUI中的颜色类型)和PaletteCore.myGreen(UIColor / NSColor)。



水下岩石



我将列出我们遇到的情况。



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


SPM — Bundler?



在这件事上,我建议做梦并在评论中进行讨论。该主题需要很好地研究,但是看起来非常有趣。顺便说一句,关于SPM的优缺点,已经有一篇有趣而相当接近的文章



SPM允许您通过将Package.swift添加到项目根目录来调用swift运行。它给我们带来什么?例如,您可以调用fastlane或swiftlint。通话示例:



swift run swiftlint --autocorrect.



All Articles