[Firebase] はじめてのCloud Functions

FirebaseのCloud Functionsを利用すると巷で話題のサーバレスなシステムを構築することができます。外部にURLを公開してRESTful APIなども作成できますし、Firebase内のイベントに合わせて特定の処理を実行することが可能です。もちろんFirestoreやRealtimeDatabaseなどと連携することもできます。

functionsはNode.js上で動作するプログラムを記述することになりますので、すでにJavaScriptやTypeScriptの経験がある方なら特別な言語仕様を覚える必要が無いのも魅力でしょう。

CloudFunctionsでHelloWorld

準備

Firebaseのコンソールからプロジェクトを作成します。すでに利用しているプロジェクトがある場合はそちらを使用しても大丈夫です。 blog.katsubemakito.net

その後CLIツールのインストールを行います。詳しくは以下のページの「1 環境の準備」の項、Googleアカウントでログインするまでの部分を参照ください。 blog.katsubemakito.net

ディレクトリの初期化

すでにFirebaseで利用しているディレクトリがあればそちらに、無ければ新規にディレクトリを作成しカレントディレクトリを移ります。今回はすでに使ってるプロジェクトがあったのでそちらに移動しました。

$ cd miku3net

ではおもむろに初期化コマンドを叩きます。

$ firebase init functions

ウェルカムメッセージが表示された後にいくつか質問を求められます。 最初に利用するプロジェクトを選択します。既存のディレクトリを利用した場合はスキップされます。

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add, 
but for now we'll just set up a default project.

次にCloudFunctionsで利用する言語をJavaScriptTypeScriptのいずれかから選択します。ここではJavaScriptを選びました。ESLintを利用するか聞かれるので任意でYes/Noを選択。ここではNoを選びました。最後に必要なモジュールをインストールするか聞かれますのでYesを選択。ネットワーク経由でモジュールをガンガン取ってきてくれます。

=== 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? JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? No
✔  Wrote functions/package.json
✔  Wrote functions/index.js
✔  Wrote functions/.gitignore
? Do you want to install dependencies with npm now? Yes

最終的に以下のようなメッセージが表示されれば成功です。

✔  Firebase initialization complete!

functionsという名前のフォルダが作成され、中に以下のようなファイルが生成されています。

スクリプトの準備

functions/index.jsを開き以下のようなコードを準備します。実際にはコメントアウトするだけですね。

const functions = require('firebase-functions');

// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions

exports.helloWorld = functions.https.onRequest((request, response) => {
  response.send("Hello from Firebase!");
});

functionsはNode.js上で動作するコードを書くことになりますので、ブラウザに依存した過去のコードなどを意識する必要はなくES2015相当の仕様で記述することができます。 ※Node v6 または Node v8

デプロイ

先ほど準備したファイルを本番サーバへ反映します。こちらもコマンド一発です。この処理はちょっと時間がかかりますので最初は不安になりますが大丈夫です、じっと待機します。

$ firebase deploy --only functions

最終的にDeploy complete!と表示が出ればデプロイに成功しています。早速Function URL (helloWorld)と表示されている箇所のURLへアクセスしてみましょう。

=== Deploying to 'test-f76bc'...

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (29.37 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: creating Node.js 6 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful create operation. 
Function URL (helloWorld): https://us-central1-test-f76bc.cloudfunctions.net/helloWorld

✔  Deploy complete!

無事にHelloWorldが表示されたでしょうか?

またFirebaseのコンソールからも作成されたことが確認できます。

その他

東京リージョンを利用する

デフォルトだとus-central1に固定で作成されてしまうため、このリージョンを変更したくなりますよね。最初はpackage.jsonで指定したり、コマンドのオプションにあるのかと思ったのですが、どうもソースコード上で直接指定するようです。

const functions = require('firebase-functions');
exports.helloWorld = functions.region('asia-northeast1').https.onRequest((request, response) => {
    response.send("Hello from Firebase!");
});

Nodeのバージョンを指定する

デフォルトだとNode v6で動作するのですが、さすがにちょっと古いのでv8で動かす設定を行います。 functions/package.jsonを開き、以下を追加します。

  "engines": {"node": "8"}

全体としては以下のようなイメージ(コメント行は記入しないでください)

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "serve": "firebase serve --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "dependencies": {
    "firebase-admin": "~7.0.0",
    "firebase-functions": "^2.2.0"
  },
  "private": true,

  // ↓こいつを追加
  "engines": {"node": "8"}
}

作成済みのFunctionを削除する

Firebaseのコンソールから削除できます。

CLIからだと以下の通り。

$ firebase functions:delete helloWorld

参考ページ

firebase.google.com firebase.google.com