雑食日誌

Vue.jsとServerless。ときどきチーム開発

Cloud Functions for Firebaseを使ってApollo Serverを構築する

はじめに

GraphQLのバックエンド実装は以下の方法があります。

  • 各言語に用意してあるライブラリ
  • Apollo Server
  • AppSync

Apollo ServerはNode.jsによるGraphQLサーバーを構築するOSSです。 クライアントだけではなくバックエンドも複数のデータソースから選択して実装することができます。 今回はCloud Functons for Firebaseを使ってApollo Serverを実装してみました。

Firebase初期設定

FirebaseのプロジェクトにCloud Functionsを追加します。言語はTypeScriptを選択しました。

$ firebase init functionsd
=== Functions Setup

A functions directory will be created in your project with a Node.js
package pre-configured. Functions can be deployed with firebase deploy.

? What language would you like to use to write Cloud Functions? TypeScript
? Do you want to use TSLint to catch probable bugs and enforce style? No
✔  Wrote functions/package.json
✔  Wrote functions/tsconfig.json
✔  Wrote functions/src/index.ts
✔  Wrote functions/.gitignore
? Do you want to install dependencies with npm now? Yes

TypeScript初期設定

TypeScriptの設定を行います。Cloud Functions for Firebaseを使用するため、 functions/ ディレクトリ内で作業します。

$ cd functins/
$ npm i -D @types/graphql @types/node typescript

tsconfig.json は以下のように編集しました。

  • JavaScriptファイルを build ディレクトリに出力
  • Node.js のCommonJS方式を使用するため、 "module": "commonjs" に変更
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "strict": true,
    "importHelpers": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "types": [
      "node"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "outDir": "build"
  },
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules"
  ]
}

Apollo Server初期設定

Cloud Functions向けのプラグインである apollo-server-cloud-functions をインストールします。

$ npm i apollo-server-cloud-functions graphql
$ npm i -D @types/graphql

サンプルとして src/index.tsApollo Serverのサンプルと同じスキーマを実装します。プラグインGCPのCloud Functionsのため、インスタンス化した ApolloServerfunctions.https.onRequest 関数の引数に代入しています。

import { ApolloServer, gql } from "apollo-server-cloud-functions";
import * as functions from 'firebase-functions';

const typeDefs = gql`
  # Comments in GraphQL strings (such as this one) start with the hash (#) symbol.

  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
  }
`;

const books = [
    {
        title: 'Harry Potter and the Chamber of Secrets',
        author: 'J.K. Rowling',
    },
    {
        title: 'Jurassic Park',
        author: 'Michael Crichton',
    },
];

const resolvers = {
    Query: {
        books: () => books,
    },
};

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: ({ req, res }) => ({
        headers: req.headers,
        req,
        res
    })
});

exports.graphql = functions.https.onRequest(server.createHandler());

ローカルで動かす準備ができたので、Firebase emulatorsを起動してみます。TypeScriptがトランスパイルされていないので、 functions/ 配下でNPMコマンドを実行してます。

$ npm run serve
✔  functions: Emulator started at http://localhost:5000
i  functions: Watching "/Users/numatakeisuke/working/poc/apollo-google-cloud-functions/functions" for Cloud Functions...
✔  functions[graphql]: http function initialized (http://localhost:5000/apollo-server-sample/us-central1/graphql).

表示されたURL(http://localhost:5000/apollo-server-sample/us-central1/graphql)をブラウザで開くとGraphQLクライアントが表示されます。 Booksからタイトルを取得すると画像のようになりました。

f:id:keinumata:20200101221227p:plain
GraphQL実行画面

まとめ

Cloud Functions for Firebaseをバックエンドに選択してApollo Serverを実装してみました。 Cloud Functions のデプロイが簡単なので、予想しいていたより早く実装できました。

今後はFireStoreのデータを返す仕組みを作ってみます。

参考