LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

大規模iOSプロジェクトのDocCをホスティングする技術

image

こんにちは、コミュニケーションアプリ「LINE」のiOSクライアントアプリにおいて開発基盤を担当している、モバイル・ディベロッパーエクスペリエンスチーム所属のfreddiです。

最近、LINEのiOSプロジェクトでは、社内のアプリ開発者向けにDocCドキュメントを公開しました。試行錯誤を重ねた結果、Swift 6.1のDocCに関する新機能や、社内インフラ、関連ツールを活用することで、使いやすく理想的なDocCドキュメントを提供できるようになりました。これにより、数百を超えるモジュールのリファレンスでも快適に参照できるようになっています。

この記事では、LINEのような数百モジュールをもつ大規模なiOSプロジェクトのDocCをWeb上にホスティングした事例を紹介します。その中で直面した課題と、その対処法についても解説します。また、Swift 6.1から導入されたDocCの新しい機能なども紹介します。

DocCとは

SwiftのDocCは、SwiftやObjective-Cを利用したプロジェクト向けの強力なドキュメンテーションツールです。コード中のコメントや、Markdownファイルから、自動でAppleが公開しているようなスタイルのドキュメントを生成します。そして、ドキュメントだけでなく、チュートリアルといったさまざまなスタイルのドキュメントを生成できます。詳しくは、AppleのDocC公式ドキュメントを参照してください

DocCのドキュメントはXcodeからドキュメントとして参照することはもちろん、Webサイトとして公開・ホスティングすることもできます。例として、弊社のgiginetが開発しているScipioは、DocCドキュメントをGitHub Pagesでホスティングしています。

今回、LINE iOSプロジェクトでは、インフラの構成やDNSを設定するといった観点でのスケールも必要だったので、社内クラウドでホスティングすることにしました。

LINE iOSプロジェクトでDocCをホスティングする上での問題点

LINE iOSプロジェクトでいざDocCをホスティングしようとすると、いくつかの大きな課題に直面しました。

多くのターゲットをまとめるページがない

これまでのDocCの仕組みでは、複数のモジュールのドキュメントを一覧するページ、ランディングページを作成する方法が提供されていませんでした。このため、各モジュールごとに別々のページを作成し、ホスティングするしかなく、モジュールを横断的に索引する手段が存在しませんでした。これではドキュメントが数百以上に及ぶプロジェクトでは非常に使い勝手の悪いものになってしまいます。

自前でランディングページを用意するアプローチも取れますが、メンテナンスや生成にはコストがかかります。また、標準に近いランディングページを構築したいという希望もありました。

利用体験の維持が難しい

大規模なLINE iOSプロジェクトにおいては、DocCドキュメントの生成量が膨大であるため、これらをホスティングするにはパフォーマンスといった特別な工夫が求められました。また、GitHub Pagesなどのサービスでは、DNS設定やパフォーマンスの柔軟な調整が難しいという問題がありました。

それぞれの問題点を克服したDocCドキュメントの構築・公開

ランディングページの問題はSwift 6.1から入った新しいDocCの機能を利用して解決し、後者は社内クラウドを用いて解決しました。ここからは、それぞれについて見ていきましょう。

Swift 6.1からの新機能を利用したランディングページの構築

Swift 6.1以前から存在している、doccコマンドにあるmergeというサブコマンドを利用すれば、生成されたDocCドキュメント(*.doccarchive)を一つにマージできます。しかし今までは単にマージするだけで、ランディングページの構築はできませんでした。

ですが、Swift 6.1から、docc mergeコマンドに--synthesized-landing-page-から始まるオプションが追加されました。 このオプションを利用すると、以下のようなランディングページが生成されたマージ済みDocCドキュメントが生成できます。

index

ページ下部には、各モジュールで用意されたチュートリアルも配置されており、ランディングページから各コンテンツにすぐに飛べるようになっています。

--synthesized-landing-page-*から始まるオプションには、以下の3つがあります。

  • --synthesized-landing-page-name - ドキュメントのタイトルとして表示する文字列(上の画像の「FreddiApp」に当たる部分)

  • --synthesized-landing-page-kind - ドキュメントのサブタイトルとして表示する文字列(上の画像の「Welcome To FreddiApp」に当たる部分)

  • --synthesized-landing-page-topics-style - ドキュメントのスタイル(上画像はcompactGrid。他にもいくつかスタイルが存在

LINE iOSプロジェクトではこのオプションを利用して生成した、ランディングページ付きのドキュメントをホスティングしています。

では、実際にこれらのオプションを利用して、どのようにDocCドキュメントを生成しているのか説明します。

docbuildを利用して.xcworkspaceからビルドする

まず、xcodebuildのサブコマンドであるdocbuildを利用して、.xcworkspaceからDocCドキュメントをビルドします。

$xcodebuild docbuild -scheme$スキーム名 \
    -workspace $xcworkspaceへのパス \
    -derivedDataPath $生成物の出力先パス \
    -destination $プラットフォームターゲットやデバイス情報 # 例:platform=iOS Simulator,name=iPhone 16 Pro Max

DocCのビルドでは、スキーム本来の生成物(アプリやフレームワーク)のビルドに加えて、ドキュメントのビルドがある分いつもより少し長くビルド時間がかかります。

生成されたドキュメントのファイル名は{ターゲット名}.doccarchiveになります。特にconfigurationを指定してなければ、指定してた出力先パス以下にあるBuild/Products/Debug-{プラットフォーム名}/ディレクトリに、ドキュメントが生成されます。

ビルドを行うと、指定したスキームでビルドされる成果物(App Extensionも含む)に依存しているターゲットのDocCドキュメントも生成されます。

docc mergeを利用して各ターゲットの.doccarchiveをマージする

次に、xcrundocc mergeコマンドを呼び出し、それぞれの.doccarchiveをマージします。先程のサンプルと同様のドキュメントを構築する際は、以下のコマンドになります。

$ xcrun docc merge FreddiApp.doccarchive HarukoKit.doccarchive ... \
    --synthesized-landing-page-name FreddiApp \ # ドキュメントのタイトル
    --synthesized-landing-page-kind "Welcome To FreddiApp"  \ # ドキュメントのサブタイトル
    --synthesized-landing-page-topics-style compactGrid \
    --output-path $生成物の出力先パス # ここでは、`merge.doccarchive`のように、末尾に`.doccarchive`をつける

Xcode 16.2に付属のdoccではまだこの--synthesized-landing-page-*オプションは使えなかったため、swift-doccレポジトリrelease/6.1ブランチをチェックアウトしてビルドしたdoccコマンドを利用することで、先行してこの機能を試すことができました。

なお、執筆時点の最新バージョンであるXcode 16.3からは、付属しているdoccコマンドで利用できますが、今後もdoccの新機能を先行して試したい時にこの方法は有効です。

静的ホスティングサイトに変換

最後に、docc process-archive transform-for-static-hostingコマンドで、静的ホスティングサイトに変換します。

$ xcrun docc process-archive transform-for-static-hosting \
    --hosting-base-path $ホスティングする際のベースパス \ # 例えば、https://example.com/docs に配置するなら、docsと指定する
    merge.doccarchive \ # マージされたドキュメントのパス
    --output-path $生成物の出力先パス

指定した生成物の出力先パスに、変換されたドキュメントを含んだディレクトリが生成されます。このディレクトリの中身をホスティングサービスにアップロードすれば、Web上に公開できます。

社内オブジェクトストレージを利用したホスティング

次に、生成したドキュメントの公開方法を見ていきましょう。

当社ではポリシー上、社内クラウドの「Verda」を利用しています。このクラウドはAmazon S3互換のオブジェクトストレージを提供しているので、これにアップロードし、静的ウェブサイトホスティング機能を使って公開しました。皆さんも、Amazon S3のバケットにアップロードする場合、同様に静的ウェブサイトとしてホスティングする機能を使えば、同様に公開することができます。また、先程も書いた通り、GitHub Pagesなどでも公開できます。

リバースプロキシを利用した体験の向上

加えて、体験を向上するために、nginxサーバーを経由し、DNSとリバースプロキシを設定して公開しています。これにより、パフォーマンスの改善も可能になりました。

gzipを利用した表示速度の改善

ドキュメントを社内に公開した直後、左のツールバーで以下のようにローディングがずっと走り、表示が非常に重くなるという問題が報告されました。

loading

この原因は、ツールバー情報を含むJSONファイルのローディングに時間がかかっているためでした。このファイルには各モジュールだけでなく、それに付随するリファレンスやサブドキュメントの情報も含まれており、サイズが約70MBに達していました。

この問題の対処法として、下記のように、nginxの設定でgzip圧縮を有効化しました。

http {
    ...
    gzip on;
    gzip_comp_level 3;
    gzip_min_length 1024;
    gzip_types text/plain text/html application/xml application/json text/css text/javascript application/javascript;
    ...
}

この結果、ダウンロードサイズを9MBまで圧縮することに成功し、表示を高速化できました。

gzip-result

LINE iOSプロジェクトのDocC構成

最終的に、私たちのDocCドキュメントは以下のような構成で構築・公開しています。

structure

より最新のドキュメントを開発者に届けられるよう、ビルドとデプロイは毎晩2時に、Jenkinsで最新の開発ブランチを元に行っています。

みんなもDocCをホスティングしよう!

上で説明したように、基本的な3つのコマンドを使用するだけで、ホスティングが可能なDocCを簡単に生成することができます。

  • xcodebuild docbuild
  • docc merge
  • docc process-archive

さらに、Swift 6.1から提供されるランディングページ作成機能を活用することで、アプリ全体に統合された形でドキュメントを構築することが可能になりました。これにより、より包括的なドキュメントの提供ができるので、ぜひご活用ください。

もしAmazon S3などを利用してドキュメントを公開する場合、大規模なアプリケーションについては、gzip圧縮をはじめとしてさまざまな最適化手法を検討することで、表示速度を向上させることが可能です。こうした取り組みは開発者体験の向上にもつながるので、ぜひ挑戦してみてください。

みなさんがこの記事を参考にして、多くのDocCドキュメントを公開されることを楽しみにしています!