この投稿は、アトラエ アドベントカレンダー11日目の記事です。
昨日は、@_YukiKawakamiの「ビジネスマッチングアプリ Yenta での MVVM + Flux 例」でした。
こんにちは、株式会社アトラエでソフトウェアエンジニアとして働く青野 (@ysk_aono) です。
本日は非常にニッチな題材ではありますが、私が開発に携わっているビジネス版マッチングアプリ Yenta iOS版のビルドフェーズで実行していることについて書いてみようと思います。
※はじめに断っておきますが、特別なことは何もしていません。笑
全体の概要
スクショで見てみるとこんな感じです。
Swiftファイルのコンパイルや、CocoaPodsが自動で設定してくれるスクリプトが入っていますね。
各フェーズについて
この中の
- SwiftLint Run Script
- SwiftGen Run Script
- Copy Localizable files, Copy files generated by Swiftgen
- Copy Google Service Info Plist
- LicensePlist Run Script
について少しずつ触れます。
SwiftLint Run Script
開発時に継続的にコードを静的解析するため、ビルドフェーズの中でSwiftLintをローカル実行しています。コードの整形 & 自動修正も同時に行なっています。
スクリプトの中身は以下です。
if [ $CONFIGURATION = "Debug" ]; then
git diff --name-only | grep ".swift$" | while read filename; do
${PODS_ROOT}/SwiftLint/swiftlint --fix --format --path "$filename"
${PODS_ROOT}/SwiftLint/swiftlint --path "$filename"
done
fi
もともとは毎回全.swift
ファイルを走査していましたが、先日SwiftLintによるwarningを全て潰し終わりました。そのため、現在はgit diff
で出力された.swiftファイルのみをLintするように変更しています。
少し話が逸れますが、この変更によってコードのビルド速度に向上が見られました。当然の結果ではあるのですが、開発者体験が大きく改善しています。
SwiftGen Run Script
SwiftGenを使って、画像や翻訳用辞書といったリソースをSwiftファイルとして自動生成し、タイプセーフに利用できるようにしています。画像やローカライゼーションのキー名の文字列をハードコードするのは嫌ですからね...
strings:
inputs: Localization/ja.lproj
filter: .+\.strings$
outputs:
- templateName: structured-swift5
output: ./Yenta/Generated/Strings.swift
xcassets:
inputs:
- Images.xcassets
- ColorPallete.xcassets
outputs:
templateName: swift5
output: ./Yenta/Generated/Assets.swift
上記のような設定ファイルを使い、SwiftGenを実行しています。
${PODS_ROOT}/SwiftGen/bin/swiftgen
Copy Localizable files, Copy files generated by Swiftgen
現在Embedded Frameworkを利用してコード群をいくつかのレイヤーに分けており、依存方向の制御や責務の分離、ビルド速度の向上を図っています。
この構造の影響で、フレームワークを跨ぐと呼び出せないファイルも存在します。SwiftGenの自動生成対象にしている翻訳ファイルもその1つとなってしまっており、これに関しては例外的にどのフレームワークからも利用できるようにしたいというニーズがあります。そのため、翻訳辞書本体と呼び出し用のSwiftファイルを各フレームワークにコピーしています。
以下のようなイメージです。
辞書の本体↓
cp -r ${PROJECT_DIR}/Yenta/Localization/* ${PROJECT_DIR}/YentaDomain/Localization-copy/
SwiftGenによって生成されたStrings.swift
↓
cp -r ${PROJECT_DIR}/Yenta/Generated/Strings.swift ${PROJECT_DIR}/YentaDomain/Generated-copy/
Copy Google Service Info Plist
アプリ開発には欠かせない存在となっているFirebaseのサービス群。これらの導入時に必要なのが、Firebase Apple プラットフォーム構成ファイル(GoogleService-Info.plist
)です。
アプリのBuild ConfigurationやSchemeが1つしかない状態で運用している場合は特に考慮する必要はない事項ですが、開発環境/本番環境への接続を切り分けたりしたいので複数で運用しているケースも多いのではないでしょうか。その際、各設定毎に異なるGoogleService-Info.plist
が欲しくなります。
そこで、以下のように異なるplistファイルを1つだけ配置するようにしています。
if [ "${CONFIGURATION}" == "Release" ]; then
cp "${PROJECT_DIR}/${PROJECT_NAME}/GoogleService/Release-GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
elif [ "${CONFIGURATION}" == "AdHoc" ]; then
...
fi
LicensePlist Run Script
LicensePlistを使って、3rdパーティライブラリのライセンス情報一覧を生成しています。非常に便利で助かっています
if [ $CONFIGURATION = "Debug" ]; then
${PODS_ROOT}/LicensePlist/license-plist --output-path $PRODUCT_NAME/Settings.bundle
fi
おわりに
淡々と書いてきましたが、やはり特段変わったことはしていないですねw
最近になってunused.rbの存在を知り、これもビルド (もしくはGitHub Actions) 時に実行したら便利かな?と考えていたりします。ビルドは開発時に必ず実行するアクションではあるので、何らかの自動化スクリプトを挿入する余地が多分にあり地味に面白いなと書いていて感じました。
各アプリがこのBuild Phaseでどういうことをやっているのか、Google検索しても案外出てこなさそうな領域な気もするので、他の事例を知ってみたいなとも思います。
短いですが、今回は以上です!!
明日は、インフラエンジニアの@shino59が記事を書く予定です。お楽しみに!