ロゴテキスト ロゴ

    Cloud Functions for FirebaseでApollo Serverを実装する

    Cloud Functions for FirebaseでApollo Serverを実装する

    Apollo Serverをどこかにデプロイして試してみたい!


    そう思って調べてみるとCloud Functions for Firebaseが対応している事が分かりました。



    Firebaseは使い慣れている事もあったため、

    Cloud Functions for FirebaseにApollo Serverをデプロイしてみる事にしました。

    検証した環境

    1 firebase 11.0.1
    2 express 4.18.1
    3 apollo-server-express 3.8.1
    4 graphql 16.5.0

    開発を行う前の準備

    先にFirebaseのWebサイトからプロジェクトを作成しておきます

    Firebaseのプロジェクトを作成する

    表示された通りに進めていきプロジェクトの作成が完了すればOKです!



    Functionsを使うためのローカル環境の作成

    Cloud Functions for Firebaseをローカルで試す方法はGoogleがしっかり用意してくれていて、

    インストール方法も丁寧にまとめられています。

    はじめに: 最初の関数の記述、テスト、デプロイ  |  Firebase Documentation


    Cloud Functions for Firebaseをエミュレートしたものを firebase-functions と言うみたいですね





    まずローカル環境を作成するためのコマンドをグローバルにインストールします。

    $ npm install -g firebase-tools

    ↑を実行するとfirebaseというコマンドが使用出来るようになります。

    $ firebase --version
    11.0.1

    firebase-toolsをインストールした最初はログインが必要になります。

    $ firebase login



    ローカルで実行するための環境を作成します

    $ firebase init functions


    いくつか質問されるため答えていきます。私は今回以下のように答えました。


    • Use an existing project・・先ほど作ったプロジェクトを選択
    • What language would you like to use to write Cloud Functions?・・TypeScript
    • Do you want to use ESLint to catch probable bugs and enforce style?・・Y
      • ESLintの導入
    • Do you want to install dependencies with npm now?・・n
      • npmを使ってライブラリをインストールするか?(私はyarnを使いたいのでここではNOを選択)


    全て答え終わると必要なファイル一式が作成されます。



    firebase functionsのライブラリをインストール

    今回は最後の質問で「NO」選択していてライブラリが未インストールになっています

    そのためライブラリのインストールから行います。



    firebase functionsの処理はfunctionsフォルダの中に書くので移動します。

    $ cd functions/


    package.jsonに記載されているnodeのバージョンと合わせるため

    nodenvを使ってnodeのバージョンを固定します。

    functions/package.json
    {
      "engines": {
        "node": "16"
      },
      ・・・
    }

    package.jsonの記載が16なので記事を書いている時LTSの16.15.0をインストール

    $ nodenv local 16.15.0


    nodeのバージョンを固定出来たらライブラリをインストールします

    $ yarn install


    npmの部分を書き換える

    firebase initした際に自動的にnpm-scriptsも作られています(便利)が、

    内部でnpmを利用しているのでyarnに書き換えます。


    具体的には serveshellstartの3つです

    functions/package.json
    "scripts": {
      "serve": "yarn run build && firebase emulators:start --only functions",
      "shell": "yarn run build && firebase functions:shell",
      "start": "yarn run shell",
      ・・・
    }


    ローカルで動くようにする

    hello worldにあたるコードがコメントアウトする形で添付されています。

    コメントアウトを外して動かせるようにします

    functions/src/index.ts
    import * as functions from "firebase-functions";
     
    // Start writing Firebase Functions
    // https://firebase.google.com/docs/functions/typescript
     
    export const helloWorld = functions.https.onRequest((request, response) => {
      functions.logger.info("Hello logs!", {structuredData: true});
      response.send("Hello from Firebase!");
    });


    ここまで出来たら試しに実行してみます!

    $ yarn run serve
    ・・・
      functions[us-central1-helloWorld]: http function initialized (http://localhost:5001/xxxxxx/us-central1/helloWorld).
    ・・・

    コマンドを実行すると沢山の情報が出力されますが、

    目を凝らすと ↑ のような1行が表示されているのでブラウザでアクセスします。


    ローカルでfirebase functionsが実行出来た

    無事文字が表示されました!



    GraphQLの実装

    firebase functionsを動かす下地が出来たので、GraphQLを動かせるようにしていきます。



    実装方法は複数あるようなのですが、

    いざという時の対応がしやすく記事も多くある expressを使った実装 をしていきます。




    まず必要なパッケージをインストールします。

    注意点としては引き続きfunctionsフォルダで実行する必要がある、ということです。

    $ yarn add express apollo-server-express graphql


    apollo-server-expressはexpressとApollo Serverを統合するためのパッケージで、

    Apollo Server公式に以下のように書かれています。

    apollo-server-express is the Apollo Server package for Express, the most popular Node.js web framework. It enables you to attach a GraphQL server to an existing Express server.


    [翻訳] apollo-server-expressは、Node.jsのWebフレームワークとして最も人気のあるExpress用のApollo Serverパッケージです。既存のExpressサーバーにGraphQLサーバーをアタッチすることが可能です。


    Choosing an Apollo Server package - Apollo GraphQL Docs より引用




    ここまで出来たらGraphQLのコードと合わせてindex.tsを書き換えていきます。



    GraphQLのコードに関しては「もしGoogle Cloud Functionsにデプロイするなら」という記事で紹介されているexampleコードを使わせてもらいます

    Deploying with Google Cloud Functions - Apollo GraphQL Docs

    functions/src/index.ts
    import * as functions from "firebase-functions";
    import express from "express";
    import {ApolloServer, gql} from "apollo-server-express";
     
    const typeDefs = gql`
        type Query {
            hello: String
        }
    `;
     
    const resolvers = {
      Query: {
        hello: () => "Hello world!",
      },
    };
     
    const server = new ApolloServer({
      typeDefs,
      resolvers,
    });
     
    const app = express();
    server.start().then(() => {
      server.applyMiddleware({app, path: "/"});
    });
     
    export const graphql = functions.https.onRequest(app);
    • typeDefsからnew ApolloServerまでのところがApollo Serverの設定
    • const appからapplyMiddlewareまでの流れがexpressとApollo Serverを統合しているところ
    • 最後の1行でfirebase functionsで使えるようにしています


    最後にtsconfig.jsonに2行追記します

    functions/tsconfig.json
    {
      "compilerOptions": {
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true
      }
    }
    • allowSyntheticDefaultImportsはESLint対策(ないとexpressのimportで怒られる)
    • esModuleInteropはビルドにコケる対策になります
      • TypeError: express_1.default is not a functionというエラーが出力されるのを解消

    esModuleInteropは以下の記事を参考にさせていただきましたmm

    ExpressでTypeError: express_1.default is not a function エラーの解消方法 - code-log




    ここまで出来たらいよいよです!

    $ yarn run serve
    ・・・
      functions[us-central1-graphql]: http function initialized (http://localhost:5001/xxxxxx/us-central1/graphql).
    ・・・


    http://localhost:5001 からはじまるサイトにアクセスすると、

    Apollo Studioが立ち上がってQueryで定義したhelloが確認出来ました!

    firebase functionsでApollo Studioを立ち上げqueryの確認が完了

    Cloud Functions for Firebaseにデプロイする

    Cloud Functions for Firebaseを利用するためには無料プランのSparkから従量制プランのBlazeに変更する必要があります。


    大量に通信しなければ無料で使えますが、場合によってはお金が発生する可能性が出てきます。




    まずfirebaseのページ > 設定 > 使用量と請求額ページ よりプランを変更します

    使用量と請求額よりプランを変更する


    SparkからBlazeへ!

    料金プランを変更する



    これでFirebase側の設定は出来たので後はデプロイするだけ。

    デプロイコマンドも最初から用意されているので非常に簡単でyarn run deployを実行するだけ!!

    $ yarn run deploy
    ・・・
      Deploy complete!
     
    Project Console: https://console.firebase.google.com/project/xxxxx/overview


    Cloud Functions for Firebaseに関数が作成されています

    Functionsに関数が作成された


    デプロイされたGraphQLはアクセスしてもApollo Studioが起動しないためcurlコマンドで確認します

    $ curl -X POST -H "Content-Type: application/json" \
     -d "{ \"query\": \"query { hello }\"}" https://us-central1-xxxx.cloudfunctions.net/graphql
    {"data":{"hello":"Hello world!"}}

    無事「Hello world!」が出力されました!デプロイ完了です!

    プロフィールの背景画像 プロフィール画像
    Yuki Takara
    都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。