Apollo Server バージョンアップしました
はじめまして、去年の夏にスペースマーケットに入社した技術部のYoshitakaです。
いよいよ寒かった冬を超え、春の陽気が感じられるようになりましたね。
一方で、挨拶して初手で「花粉が辛くて...」と言ってしまうくらいには花粉症にとってはしんどい時期ですよね。
それでも僕は冬よりも夏が好き派なので、徐々に暖かくなってきている感覚はとにかく嬉しい限りです。
ということで今回は、入社後初めてのブログ記事投稿となりますので、入社後早々に担当した Apollo Server のバージョンをV2系からV3系にバージョンアップした時のことについて思い出しながらまとめてみます!
僕は入ったばかりの頃、「スペースマーケットのサービス内の小さなバグ改修から入っていくのかな〜」とイメージしていたのですが、
ある日、「大変だと思いますがこちらをお願いします」と言われて今回のApollo Server バージョンアップをすることになったのを覚えています笑
入社した当初はApolloに限らずGraphQLの知識すらほとんどない状態だったので苦戦しました(あと英語難しい)。
同じような方のお役に少しでも立てれば幸いです。
それではみていきます。
前提
弊社のスペースマーケットというサービスでは、バックエンド側は単一のアプリケーションで構成されておらず、検索サービスや予約サービス等複数のサービスを分離させたマイクロサービスアーキテクチャでサービスが構成されています。
そして、それと同時に各サービスから提供されているGraphqlスキーマを 、Apollo Federation を採用することによって、Gatewayを通じて単一のGraphqlスキーマとしてクライアントに提供する手法をとっています。
詳細についてはこちらの記事にて、非常に丁寧に解説されておりますのでぜひご覧ください。
今回は、Apollo Server-side caching を利用可能とする目的で、Gatewayそのものと、検索サービスの合計2つのリポジトリの Apollo Server をバージョンアップしました。
Apollo Server バージョンアップ手順
Apollo Serverのバージョンアップ手順についてなのですが、公式ドキュメントに Migrate to Apollo Server 3 として記載があります。
を信じてひとつひとつ見ていきましょう。
簡単でありますように...🙏
依存関係の確認
まずはライブラリの依存関係について整理していきます。
下記の二点をご確認ください。
Node.js
Node.js バージョン 12以降が必要なので、Node.jsバージョンが足りていない場合はこちらのバージョンアップからお願いします。スペースマーケットの場合も最初にNode.jsのバージョンアップ作業を行いました。
graphql
graphqlもバージョン15.3.0以上が必要となっています。
削除されたインテグレーションの確認
バージョンアップ前にはデフォルトで組み込まれていたが、バージョンアップ後で削除された機能としては下記の2つがありました。
subscriptions-transport-ws
graphql-upload
これらは別途で独自のメカニズムを利用できるように組み込みから削除しているようですね。
ただ、こちらについてはスペースマーケットでは利用していなかったので、今回は割愛します。
削除されたコンストラクタオプション
ApolloServerのコンストラクタとしていくつか削除されたオプションがあるので、それにどう対応していくのかをバージョンアップ前後で見ていきます
extensions
バージョンアップ前でextensionsオプションとして記述していたgraphqlの拡張機能では制約が多かったので、プラグインとして自前で書き直してくださいとありますね。
下記のように書き換えました。
// バージョンアップ前
import CustomLogger from '../extensions/customLogger';
extensions: [() => new CustomLogger()],
// バージョンアップ後
import { CustomLogger } from './apolloPlugins';
plugins: [
CustomLogger(),
]
extensions内で生成しているCustomLoggerインスタンスの定義ファイルをプラグインファイルとして書き直したのですが、
元のクラス定義ファイルでは、バージョンアップ後に削除された'graphql-extensions'からインポートしたクラスを使用していたので、この辺りの移行に少々苦戦しました。
最終的なクラスファイルは下記のようになりました。
// extensions用に書かれたクラスファイル(書き直し前)
import {
GraphQLExtension,
EndHandler,
GraphQLResponse,
} from 'graphql-extensions';
export default class CustomLogger implements GraphQLExtension {
requestDidStart(): EndHandler {
console.log("hoge");
}
willSendResponse(o: { graphqlResponse: GraphQLResponse }): void {
console.log("fuga");
}
}
// plugins用に書いたクラスファイル(書き直し後)
import {
BaseContext,
GraphQLRequestContext,
GraphQLRequestContextWillSendResponse,
} from 'apollo-server-plugin-base';
function CustomLogger() {
return {
async requestDidStart(requestContext: GraphQLRequestContext<BaseContext>) {
console.log("hoge");
return {
async willSendResponse(
requestContext: GraphQLRequestContextWillSendResponse<BaseContext>,
): Promise<void> {
console.log("fuga");
},
};
},
};
}
export { CustomLogger }
playground
playgroundオプションもpluginsに移行します。
trueの場合はApolloServerPluginLandingPageGraphQLPlayground、
falseの場合はApolloServerPluginLandingPageDisabled
をインポートし、指定してください。
import {
ApolloServerPluginLandingPageDisabled,
ApolloServerPluginLandingPageGraphQLPlayground,
} from 'apollo-server-core';
// バージョンアップ前
playground: env.XXX === 'XXX' ? true : false
// バージョンアップ後
plugins: [
env.XXX === 'XXX'
? ApolloServerPluginLandingPageGraphQLPlayground()
: ApolloServerPluginLandingPageDisabled(),
]
engine
engineオプションは、apolloオプションに記述します。
engine.apiKeyは、apollo.keyとなるようです。
// バージョンアップ前
engine: { apiKey: process.env.APOLLO_ENGINE_API_KEY },
// バージョンアップ後
apollo: {
key: process.env.APOLLO_ENGINE_API_KEY,
},
まとめ
コンストラクタオプションの移行後、無事にApolloServerインスタンスを生成できたら、あとはawait server.start()を書いてあげてください。バージョンアップ後では必須となっているようです。
こんな流れでスペースマーケットサービス内のGatewayと検索サービスのApollo Serverをバージョンアップすることができました。
プラグインの書き直し周りは苦戦しましたが、最初に公式ドキュメントに書いてあった通り、ほとんどコードを変更することなくバージョンアップすることができてしまいました。公式ドキュメントでバージョン移行についてかなり丁寧に書かれているのもありがたいですね。
かなりコアな部分ではありましたが、最初のタスクとしてはかなりの技術的チャレンジをさせてもらったなと思っています❗️
参考
最後に
スペースマーケットは挑戦すること前向きに後押ししてくれる雰囲気で溢れていると思っています!スペースシェアという文化に興味があったり、技術的に色々挑戦がしてみたいという方、ぜひお気軽にご応募ください!お待ちしております!
この記事が気に入ったらサポートをしてみませんか?