dely Tech Blog

クラシル・TRILLを運営するdely株式会社の開発ブログです

Xcodeプロジェクト管理ツール「Tuist」を試している

こんにちは。
delyコマース事業部のJohn(@johnny__kei)です。
この記事は「dely #1 Advent Calendar 2020」の20日目の記事です。

adventar.org

adventar.org

昨日はtakaoさん(takaoh717)の「エンジニアが始めるプロダクトマネジメント最初の一歩」という記事でした。

はじめに

今回は、iOS開発で試しに使っているTuistというツールを紹介したいと思います。 TuistはXcodeプロジェクトの生成、管理を楽にしてくれるコマンドラインツールです。
似たようなツールでXcodeGenがあります。

大きな特徴は、Project.swift というファイルでの中でプロジェクトの定義をSwiftで記述するところです。 ここがイケてるやんと思って使い始めました。
(↓サイトトップに記載されている例)

import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.featureFramework(
  name: "Home",
  dependencies: [
    .project(target: "Features", path: "../Features"),
    .framework(path: "Carthage/Build/iOS/SnapKit.framework")
    .package(product: "KeychainSwift")
  ]
)

また、*.xcodeproj*.xcworkspaceはgitignore前提なので、コンフリクトして辛い思いをすることはありません。

SoundCloudでの開発にも使われているようです。 developers.soundcloud.com

Tuistはドキュメントもいい感じで、さくっと試してみるのも簡単です。

Getting Started

tuist.io ドキュメントに沿って雰囲気をお伝えします。

tuist init

tuist init で始めると以下のようなフォルダ構成が生成されます(tuist ver 1.28.0)

|--.gitignore
|--Project.swift
|--Targets
| |--MyApp
| | |--Resources
| | | |--LaunchScreen.storyboard
| | |--Sources
| | | |--AppDelegate.swift
| | |--Tests
| | | |--AppTests.swift
| |--MyAppKit
| | |--Sources
| | | |--MyAppKit.swift
| | |--Tests
| | | |--MyAppKitTests.swift
| |--MyAppUI
| | |--Sources
| | | |--MyAppUI.swift
| | |--Tests
| | | |--MyAppUITests.swift
|--Tuist
| |--Config.swift
| |--ProjectDescriptionHelpers
| | |--Project+Templates.swift

tuist edit

tuist editで定義用Xcodeプロジェクトを開きます。

f:id:JohnnyKei:20201217204204p:plain

Project.swift はこんな感じです。

let project = Project.app(name: "MyApp",
                          platform: .iOS,
                          additionalTargets: ["MyAppKit", "MyAppUI"])

Project.app(xxx)というのはProject+Templates.swiftに記載されているHelperメソッドです。
MyAppというアプリケーションとMyAppKitMyAppUIというEmbeddedFrameworkがあるプロジェクトを定義しています。

tuist generate

tuist generateProject.swiftの定義からMyApp.xcworkspaceMyApp.xcodeprojが生成されます。 MyApp.xcworkspace を開くとこんな感じです。 f:id:JohnnyKei:20201217210257p:plain

実践編

他にどんな感じかで使うかの例を少し挙げます。

WorkSpace.swift で複数のプロジェクトをまとめる

複数のProject.swiftを作成してWorkspace.swiftでまとめることもできます。 Getting Startedのときから、フォルダ構成も若干変えています。

f:id:JohnnyKei:20201217213103p:plain

|--.gitignore
|--Projects
| |--MyApp
| | |--Project.swift
| | |--Resources
| | | |--LaunchScreen.storyboard
| | |--Sources
| | | |--AppDelegate.swift
| | |--Tests
| | | |--AppTests.swift
| |--MyAppKit
| | |--Project.swift
| | |--Sources
| | | |--MyAppKit.swift
| | |--Tests
| | | |--MyAppKitTests.swift
| |--MyAppUI
| | |--Project.swift
| | |--Sources
| | | |--MyAppUI.swift
| | |--Tests
| | | |--MyAppUITests.swift
|--Tuist
| |--Config.swift
| |--ProjectDescriptionHelpers
| | |--Project+Templates.swift
|--Workspace.swift

MyApp/Project.swiftはこんな感じです。

let project = Project.app(name: "MyApp", platform: .iOS, dependencies: [
    .project(target: "MyAppKit", path: .relativeToManifest("../MyAppKit")),
    .project(target: "MyAppUI", path: .relativeToManifest("../MyAppUI"))
    
])

tuist generateで生成されたMyApp.xcworkspaceはこんな感じになります。

f:id:JohnnyKei:20201217213841p:plain

特定のプロジェクトにフォーカス

tuist focus XXXでとその依存関係を解決したxcworkspaceが生成されます。
機能単位でXcodeプロジェクトがわかれているといじらないコードやターゲットも表示されないのでプロジェクトファイルがシンプルになるし、Indexingも早くなり、ファイル検索も膨大な中から探さなくて良くなるので、開発が捗ります。 SwiftがちょっとわかるデザイナーがUIComponentの確認や調整をするときは、UIのみのプロジェクトを動かす、などができます。(Xcode Previewを使用など)

tuist focus MyAppUIをした時はこんな感じです。 f:id:JohnnyKei:20201217214154p:plain

依存関係が一目でわかる

tuist graphで依存関係のグラフを生成できます。
プロジェクト間にどのような依存関係があるか一目でわかるので便利です。

f:id:JohnnyKei:20201218141929p:plain

μFeatures

tuistはμFeaturesという考えた方をしていて、僕たちの開発において、だいぶ参考にしています。

tuist.io

ほかにもいっぱい

ほかにもいっぱい機能があるので、気になった方はぜひ触ってみてください。

さいごに

delyでは、定期的にイベントを行っています。 僕も中の人ながら、聴くのを楽しみにしています。 メンバーがどんな感じの雰囲気かもわかるので、ぜひお気軽にご参加ください。

bethesun.connpass.com

各ポジション募集中なので、気になるなぁとか思った方はぜひイケてる募集サイト見てみてください。 join-us.dely.jp

明日はこばさん(@kazkobay)による記事です。お楽しみに!