[ING] - Apollo 0.x系と1.x系の差分調査用リポジトリ
Apolloを利用したGraphQLでの処理において、0.x系と1.x系で大きな変更があったので、相違点がある部分を中心にまとめたものになります。
※こちらの内容に関しては、2023年10月17日に開催された「Mobile勉強会 Wantedly × チームラボ #11」でも登壇しました。登壇資料内では、業務内で得られた知見や簡単なサンプル開発を通じて得られた学びの中で「基本のき」の部分も合わせてまとめています。
コード自動生成処理に関連する部分は抜本的に変更が入っていました。2023年9月時点での最新版はv1.5であることや、6月中にv0.x系からバージョンアップされた際の変更内容がかなり破壊的であったので、今後の動向や変更内容に関しては引き続きキャッチアップを継続していきます。
まず前段として、0.x系での導入手順とBuildまでの流れを軽く触れておきます。
【まとめ図解】
過去バージョンでは、XcodeをBuildするタイミングでGraphQLのコード生成処理を実行する様な形を取っていました。
Apolloのメジャーバージョンアップが実施された事に伴い、CLI関連をはじめ内部機能についても破壊的な変更がされました。
その中でも、以前にApolloのv0.x系を過去に導入していた場合からv1.x系にバージョンアップをする際は下記のマイグレーションガイドに沿って実施していく事になります。特にCLI関連やコード自動生成処理についても抜本的な変更がされている点に注意が必要です。
※ Apolloマイグレーションガイドについては「v1.0→v1.2」&「v1.2→v1.3」に関するドキュメントも用意されています。
【CLIに関する変更点】
v1.x系では、Swift Package Manager経由でApolloを導入してApolloを導入した場合にはXcodeからCLIツールをインストールする事ができます。これまでのnode.js経由でのインストール方式ではなくXcodeを経由したインストールとなったので、設定も随分としやすくなっています。
【コード自動生成に関するコマンド】
# ①`apollo-codegen-config.json`の雛形を作成する
$ ./apollo-ios-cli init --schema-namespace CountriesSchema --module-type embeddedInTarget --target-name SimpleGraphQLPractice (--overwrite)
# ② apollo-codegen-config.jsonの内容をProjectに合わせて記載する
# ③ schema定義ファイル(schema.json)をapollo-ios-cli経由でダウンロード or 直接ダウンロードしProject内に配置
# ※ schema定義ファイルが正しく設定されている場合は下記コマンドを実行してダウンロードができます
$ ./apollo-ios-cli fetch-schema
# ④ 定義した`apollo-codegen-config.json`からSwiftコードを自動生成する
$ ./apollo-ios-cli generate
下図は今回のサンプルプロジェクトで記載しているapollo-codegen-config.json
の一例になりますが、内容には現在お使いのProject構成に合わせて設定することになります。
【コード自動生成処理後に関する】
下図は今回のサンプルプロジェクト(Example2)で自動生成したコードの概要になります。
サンプルの構成はオーソドックスな構成をベースに考えて、View要素と関係する処理については@Published private(set) var (※変数名)
で定義した変数との双方向Bindingの様な形を前提として処理を組み立てています。
【GraphQL側の処理をasync/awaitで取り扱う】
// 実装の参考:
// 「apollo-ios」内のIssue内のディスカッションで紹介されていたコードを参考にしています。
// Apollo内で用意されているQuery & Mutationの実行処理をasync/awaitでラッピングしている。
// https://github.com/apollographql/apollo-ios/issues/2216
// MARK: - ApolloClient Extension
extension ApolloClient {
// GraphQLのQueryをする処理をasync/awaitの処理内で実行する
@discardableResult
func fetchAsync<Query: GraphQLQuery>(
query: Query,
cachePolicy: CachePolicy = .default,
contextIdentifier: UUID? = nil,
queue: DispatchQueue = .main
) async throws -> GraphQLResult<Query.Data> {
// MEMO: withCheckedThrowingContinuationでErrorをthrowする形にしています。
return try await withCheckedThrowingContinuation { continuation in
fetch(
query: query,
cachePolicy: cachePolicy,
contextIdentifier: contextIdentifier,
queue: queue
) { result in
switch result {
case .success(let value):
continuation.resume(returning: value)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
// GraphQLのMutationをする処理をasync/awaitの処理内で実行する
@discardableResult
func performAsync<Mutation: GraphQLMutation>(
mutation: Mutation,
publishResultToStore: Bool = true,
queue: DispatchQueue = .main
) async throws -> GraphQLResult<Mutation.Data> {
// MEMO: withCheckedThrowingContinuationでErrorをthrowする形にしています。
return try await withCheckedThrowingContinuation { continuation in
perform(
mutation: mutation,
publishResultToStore: publishResultToStore,
queue: queue
) { result in
switch result {
case .success(let value):
continuation.resume(returning: value)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
}
【Example1】
国情報一覧表示→詳細表示をするだけのシンプルなものになります。
- GraphQL Server:
https://countries.trevorblades.com/graphql
国一覧画面 | 国詳細画面 |
---|---|
![]() |
![]() |
【Example2】
お料理メニュー一覧表示→絞り込み検索やお問い合わせ送信をするだけのシンプルなものになります。
- GraphQL Server:
http://localhost:4000/graphql
※ ローカル環境で起動して確認をする様にしてください。
# package.jsonに記載している内容をインストールする
$ yarn
# GraphQL Serverを起動する
$ yarn dev
メニュー検索画面 | お知らせ一覧画面 |
---|---|
![]() |
![]() |
お問い合わせ画面 | お問い合わせ入力状態 |
---|---|
![]() |
![]() |
v0.x系での実装については、下記講座を受講した際に紹介されていたものを参考にして、当リポジトリで紹介している2種類のサンプルコードはそれを参考にした上で1.x系利用した実装へ置き換えたものになります。
このサンプルでは「Apollo + Express」を利用した環境で動作する、疑似的なGraphQLサーバーから値を取得する形を取っています。 下記の様な手順で環境構築を実施しました。
# Backendディレクトリ内に疑似的なサーバーに関するコードを作成する
$ cd Backend
# プロジェクトの新規作成
$ yarn init -y
# Apollo Serverパッケージを追加する(Apollo + Express構成)
$ yarn add apollo-server apollo-server-express express graphql cors
# Typescriptパッケージを追加する
$ yarn add -D typescript @types/node
# tsconfig.jsonを新規作成する
$ npx tsc --init
# ts-node&ts-node-devパッケージを新規作成する(TypeScriptコード変更を検知し再起動するため)
$ yarn add -D ts-node ts-node-dev
# 参考1: Apollo+Expressで始めるGraphQL超入門 ~ GraphQLをざっくり理解する
# https://qiita.com/Zonoma/items/5de4b14dcd839db5f148
# 参考2: TypeScriptでApollo-Serverを構築する
# https://qiita.com/omukaik/items/4b31b771c674fcea9118
# 参考3: 【GraphQL】Apollo ServerやTypeScriptを使ってGraphQLのAPIを開発する
# https://isub.co.jp/graphql/getting-started-with-apollo-server/
【GraphQLそのものについて理解を深める参考資料】
【環境構築手順の参考資料】
【Apollo Serverを利用したGraphQLサーバーの参考資料】
- Node.js&TypeScriptでGraphQL入門:Apollo Server(V4)を使って簡単にAPIを実装
- Apollo Server with TypeScrip
- GraphQLのページネーション機能を実装する方法: Apollo client + express-graphql
※ 今回はPagination機能は実装していませんが、機会があれば挑戦してみたいと感じています。