Firebase
cloudfunctions
FirebaseDay 16

Firebase Functions 上に GraphQL サーバーを実装する

この記事は1ヶ月後の自分のネタ切れにつきアドベントカレンダーの記事ということになりました

Why

SPA や モバイルアプリ だととりあえず Firebase Functions に graphql エンドポイントを一個マウントして金で殴ってスケールさせるところからスタートするのがいいと思います。金の弾丸というやつです。

この環境は、query と mutation は実装できるけど、 Cloud Functions のライフサイクルの都合上、 wsバックエンドのsubscription は実装できません。そこは Firestore とか使ってなんとかできるんでいいかって感じ。

自分の用途としては、Firestore の write系は一律禁止、 read 系は firebase.rules で制御しつつ subscribe して、リアルタイムではない複雑な問い合わせやロジック検証付きの副作用を GraphQL に寄せる、みたいな使い方を想定してます。

この記事で解説しないこと

  • firebase にデプロイする手順
  • graphql スキーマ定義やリゾルバの実装方法
  • webpack や npm install や package.json

functions 定義

これだけ。

functions/index.js
const functions = require('firebase-functions')
const express = require('express')
const { graphqlExpress } = require('apollo-server-express')
const bodyParser = require('body-parser')
const { makeExecutableSchema } = require('graphql-tools')

const schema = makeExecutableSchema({
  typeDefs: [/* Your schema.graphql */],
  resolvers: {/* Your resolver */}
})

const server = express().use(
  bodyParser.json(),
  graphqlExpress({ schema, context: {} })
)

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

makeExecutableSchema でどのようにgraphqlサーバーを実装するかは別途調べてください。
https://github.com/apollographql/graphql-tools
https://github.com/mizchi-sandbox/play-graphql-server

クライアントから graphql へ リクエストを送る

firebase deploy でデプロイ(略)

Firebase の rewrite ルールに graphql function を指定

firebase.json
{
  "functions": {
    "source": "functions"
  },
  "hosting": {
    "rewrites": [
      {
        "source": "/api/graphql",
        "function": "graphql"
      }
    ]
  }
}

firebase serve などでローカルサーバーの実行

ApolloClient からリクエスト

src/graphqlClient.js
import 'isomorphic-fetch'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import gql from 'graphql-tag'

const client = new ApolloClient({
  link: new HttpLink({ uri: 'http://localhost:5000/api/graphql' }),
  cache: new InMemoryCache()
})

client.query({
  query: gql`<your query>`
}).then(ret => {
 console.log(ret)
})

注意:2017/11/27 現在、このビルドエラーを踏んだのでapollo-linkへのワークアラウンドが必要 https://github.com/apollographql/apollo-link/issues/248

TODO

  • あとでサンプルプロジェクトを公開
  • Firebase Auth との認証系を作る
  • 認証トークンを使って Firestore を殴る

https://github.com/firebase/functions-samples/blob/master/authorized-https-endpoint/functions/index.js