Firebaseの技術情報サイト

Firebaseの技術情報サイト

Firebase活用の為の技術情報サイトです

Firebaseでバックエンドの実装をExpressで!

Firebaseでバックエンドの実装をExpressで!

Firebaseでバックエンドの処理を実装するには「ファンクション(Functions)」を使います。この記事では、Node.jsでバックエンドを実装する際に広く利用されているExpressのモジュールを使ってFirebaseのバックエンド機能を実装する方法を解説しています。

Firebaseのバックエンド(Functions)利用の手順

最初に、Firebaseのバックエンドを利用するための手順を簡単に説明します。 他の機能と同じで、Firebaseプロジェクトを作成します。

その後は、

  • Firebaseのプロジェクトフォルダの作成
  • 「firebase init」でFirebaseのプロジェクトフォルダの初期化
  • 必要なモジュールのインストール
  • バックエンドのコードの作成
  • Typescriptを利用する場合、「コンパイル」
  • 開発用のPCでテスト
  • インターネットに公開(デプロイ)

Firebaseのプロジェクトフォルダの作成

これは、開発用のPCでFirebaseのバックエンドのプロジェクトフォルダを作成します。要領はFirebaseのホスティングの設定の場合とほぼ同じです。フォルダを新規に作成するだけです。

フォルダを作成したら、作成したフォルダに移動します。 FirebaseのSDKをインストールします。すでに「-g」オプションを付けてインストールしている場合は不要です。

$ npm install -g firebase-tools

そのあとで、Firebase Admin SDKをインストールします。Firebaseのファンクションの機能を利用する場合は必要になります。

$ npm install --save firebase-admin

「firebase init」を実行

Firebaseにログインしていない場合はFirebaseにログインして、「firebase init」を実行します。

$ firebase login
$ firebase init

質問に答えながら、フォルダの初期設定を行います。

ポイントは、「hosting」と「functions」を有効にします。 途中で開発に使用する言語を選択する部分があります。「Javascript」か「Typescript」を選択できます。この記事ではTypescriptで開発することを前提に書いています。

必要なモジュールのインストール

バックエンドで利用するモジュールをインストールします。「firebase init」を実行する際に、「functions」を選択すると、Firebaseのプロジェクトフォルダに「functions」というフォルダが作成されるので、必要なモジュールのインストールは「functions」のフォルダに移動して行います

インストールするモジュールは

  • Express

のみです。ExpressはNode.jsを使ったバックエンドのフレームワークとして広く使われています。 インストールは以下のコマンドを実行します。

$ npm install express

バックエンドコードの作成

Javascriptで開発する場合はFirebaseのプロジェクトフォルダの下のfunctionsの「index.js」を編集します。 この記事ではTypescriptでの開発を前提にしているので、functions/srcの下にある、「index.ts」を編集します。

今回の例ではバックエンドからFirebaseのデータベース(Cloud Firestore)にお問合せ内容を保存する処理を行っています。そのため、Firebaseコンソールの設定から、「サービスアカウント(Service accounts)」にいって秘密鍵(privae key)を作成します。 作成すると、秘密鍵を含んだファイルがダウンロードされるので、「serviceAccountKey.json」の名前で、Firebaseプロジェクトフォルダの下のfunctionsのフォルダの下に保存します。

このファイルをバックエンドのFirebaseの初期化で使用しています。 初期化には、Firebase Cloud FirestoreのURLも必要です。

以下のコードが今回の実装例のサンプルコードです

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import * as express from "express";
// Firebase Admin SDK の秘密鍵(Private key)
const serviceAccount = require("../serviceAccountKey.json");
// お問合せを保存するコレクション
const FB_COLLECTION_QUERY = "query";
// Express サーバー
const app = express();
// Firebaseの初期化
const firebaseAdmin: admin.app.App = admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://sample-xxxx.firebaseio.com",
});
// お問い合わせのURL (/post)
app.get("/post", (req: express.Request, res: express.Response) => {
  const email = req.query.email ? req.query.email : "";
  const subject = req.query.subject ? req.query.subject : "";
  const message = req.query.message ? req.query.message : "";
  const name = req.query.name ? req.query.name : "";
  const query = {
    email: email,
    subject: subject,
    message: message,
    name: name,
  };
  // Fiebaseにお問い合わせを保存
  firebaseAdmin
    .firestore()
    .collection(FB_COLLECTION_QUERY)
    .add(query)
    .then((doc) => {
      // 処理成功
      console.log(doc.id);
      // レスポンスの返信
      res.end(JSON.stringify({ result: true, message: "success" }));
    })
    .catch((error: any) => {
      // 処理失敗
      console.log(error.message);
      // レスポンスの返信
      res.end(JSON.stringify({ result: false, message: error.message }));
    });
});
// Functionsのエキスポート
exports.app = functions.https.onRequest(app);

Typescriptを利用する場合コンパイルをします

このバックエンドのコードを実行するにはまず、コンパイルが必要です。 Firebaseのプロジェクトフォルダの下のfunctionsのフォルダで以下のコマンドを実行します。

npm run build

コンパイルすると、実行のための「Javascript」のコードが、functions/libの下に作られます。Typescriptで書かれたコードも実行時はJavascriptになります。

firebase.jsonの変更も必要です。「hosting」の設定に「rewrites」を追加します。すべてのルートを「app」で処理するように変更します。

{
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  },
  "hosting": {
    "public": "public",
    "rewrites":[{
      "source":"**",
      "function":"app"
    }],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

開発用のPCでテストします

コンパイルが済んだら、テスト用のサーバーを起動します。起動には以下のコマンドを実行します。

$ firebase serve

標準設定の場合、「http://localhost:5000」でアクセスできます。

今回は検証しやすいようにWebブラウザから簡単にお問合せ内容を送れるように、HTTPのGETメソッドを使ってお問合せ内容を送信しています。

お問合せ内容はWebブラウザのURLで次のように指定します(開発用のサーバーの場合)

http://localhost:5000/post?email=xxxx@xxxx.com&subject=Test&message=This is a test message&name=Silicon Valley Super Ware

の様に入力してリターンキーを押すとバックエンドのサーバーに情報が送られます。

バックエンドの処理が成功した場合はブラウザに以下のようなレスポンスが表示されます。

{"result":true,"message":"success"}

実際のアプリでは?

実際のアプリではHTMLのフォームを作成して、「/post」でクエリーパラメータを指定して、HTTPのGETで送れば、データがFirebaseのデータベースに保存されるようになっています。

今回は検証しやすいようにHTTPのGETで送る方法を紹介しています。実際のアプリケーションを作る際は、HTTPのGETでお問い合わせを入力するフォームを表示できるようにバックエンドでページを用意して、フォームの送信ボタンが押された際に、「HTTP POST」で送信するように作ると、フロントエンドのコードなしでお問合せフォームの処理を行うことが可能です。(Javascriptを無効にしているWebブラウザでも利用可能になります)

こちらの実装方法ばまた別の記事で紹介する予定です。

まとめ

Firebaseのバックエンドの機能を使ってサービスを実装すると、Javascriptを有効にしていないWebブラウザでもサービスを利用可能にすることができます。「お問合せフォーム」をシンプルなものは、フロントエンドのフレームワークのReactやVueを利用したり、HTMLにJavascriptを埋め込むだけでも実現可能です。

しかし、バックエンドを利用して実装すると、セキュリティルールはシンプルになります。そして、Javascriptを無効にしているWebブラウザでも利用が可能になります。

今回の実装例で使用しているセキュリティルールです

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

このルールの場合、フロントエンドからは一切Firebaseのデータベースにアクセスすることはできません。 バックエンドのFirebase Admin SDKからアクセスする場合は全てのデータにアクセス可能です。

セキュリティルールが複雑になってしまうケースなどはバックエンドでの実装を検討するとセキュリティルールをシンプルにできます。