Old Sunset Days

FirebaseのCloud FunctionsでHello World

日付 タグ firebase カテゴリ others

目次

Firebaseでサーバーレス環境

サーバーレス環境をちょっと使ってみたくて、FirebaseでCloud Functionsを使ってHello Worldを試してみた。サーバーを用意せずに、バックエンドでデータベースへの書き込みやHTTPSリクエストなどのイベントをトリガーにしてコードを実行できる仕組み。 AWSだとAWS Lambdaが同等なサービスに当たる。

自分はAWS Lamdaも使ったことなければ、Firebaseでサポートされる言語であるNode.jsに関しても初学者なので、あくまでも今後のためにサーバーレス環境を使ってみようと思った次第。

Hugoは静的なサイトジェネレーターで、できることに制限があるので、それをFirebase使って何か補ったりすることができるのかな?とぼんやり考えていたこともある。まあ、Hugoはその分、レスポンス軽快でシンプルなので、あまり余計なことをいろいろとやると複雑になってしまうのだが。

ここで前提環境としてはMacを利用してHello Worldのテストをしていく。

Firebaseサイトでのプロジェクト作成

まずはGoogleのサービスなのでGoogleのアカウントがあることが前提だが、GoogleのアカウントでFirebaseのページにログインする。

https://firebase.google.com/?hl=ja - Firebase

ログインしてコンソールへ移動。アプリが紐づく何かしらのプロジェクトが必要なので、 新規プロジェクトを作成する。

「プロジェクトを追加」

プロジェクトの名前を決めて、

次にGoogle Analyticsを有効にするかどうかだが、デフォルトで有効なのだが、そのまま進める。

Google Analyticsでのアカウントを選択するので、同じgoogleアカウントを利用。

するとプロビジョニングが始まるのでしばし待つ。

準備ができたので、とりあえずOK。

ローカルにFirebaseの開発環境を構築する

Firebaseを使うにはNode.jsの実行環境が必要なのだが、まだなければHomebrewでインストールをするか、

https://nodejs.org/ja/download/ - Node.js

Node.jsのサイトからインストーラーを使ってインストール。

Node.jsのパッケージ管理ツールnpmが利用できるようになっていることをまずは確認する。
自分の環境でのバージョンをチェックすると、

$ npm -v
6.14.8

となっていた。さて、npmコマンドが利用できる状態になっていれば、FirebaseのCLI環境をインストールするために

$ npm install -g firebase-tools

入ったfirebaseのツールのバージョンを確認しておく。

$ firebase -V
8.12.0

最初にfirebaseにログイン。

$ firebase login
i  Firebase optionally collects CLI usage and error reporting information to help improve our products. Data is collected in accordance with Google's privacy policy (https://policies.google.com/privacy) and is not used to identify you.

? Allow Firebase to collect CLI usage and error reporting information? (Y/n)

これでブラウザが開いて許可宣言の設定になる。firebaseで作業するので許可をする。

作業ができる状態になったので、今回のアプリ用に作業するローカルディレクトリの作成

$ mkdir myhelloworld
$ cd myhelloworld

先ほど作ったMyHelloWorldプロジェクトのProject IDを調べておく

$ firebase projects:list
✔ Preparing the list of your Firebase projects
┌──────────────────────┬──────────────────────────┬────────────────┬──────────────────────┐
│ Project Display Name │ Project ID               │ Project Number │ Resource Location ID │
├──────────────────────┼──────────────────────────┼────────────────┼──────────────────────┤
│ MyHelloWorld         │ xxxxxxxxxxxxxxxxxx       │ xxxxxxxxxxx    │ [Not specified]      │
└──────────────────────┴──────────────────────────┴────────────────┴──────────────────────┘

Project IDを確認しておき、作業ディレクトリの初期化スタート。

$ firebase init

どの機能をセットアップするかでは、
Functions: Configure and deploy Cloud functions
を選択。

新規にプロジェクト作るか聞かれるので先ほど作ってあったProject IDを使うので、
Use an existing project
を選択。そして、先ほどのProject IDのプロジェクトを選択する。

どの言語を利用するかの選択があるので、
JavaScript
を選択。

あとは

? Do you want to use ESLint to catch probable bugs and enforce style? Yes
? Do you want to install dependencies with npm now? Yes

を回答で最後に

✔  Firebase initialization complete!

と出ていればOK。

lsコマンドで見るとfirebase.jsonファイルとfunctionsディレクトリができている。

$ ls
firebase.json	functions

ここでfunctions/index.fsを見てみる。

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) => {
//   functions.logger.info("Hello logs!", {structuredData: true});
//   response.send("Hello from Firebase!");
// });

これを編集して/helloworldを叩くと、“Hello World!“という文字列が表示されるようにする。

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

exports.helloWorld = functions.https.onRequest((request, response) => {
   functions.logger.info("Hello logs!", {structuredData: true});
   response.send("Hello World!");
});

ここで一旦ローカル環境での動作を見ておく。作業ディレクトリmyhelloworldディレクトリで、

$ firebase serve

これでローカルでエラーなくサーバーが起動すれば、

✔  functions[helloWorld]: http function initialized (http://localhost:5000/myhelloworld-xxxxx/us-central1/helloWorld).

こんなようなメッセージが出ているはずなので、ブラウザで該当URLページを開くと、“Hello World!“と表示される。 これでローカル環境での動作はOKっぽい。

ローカルで起動しているサーバーを止めるには
Ctrl + C
で終了する。

作ったWebアプリをFirebaseにデプロイする

今しがた作ったHello Worldを表示するアプリをデプロイするには、

$ firebase deploy --only functions

なのだが、実はここでつまづいた。

Error: HTTP Error: 400, Billing account for project 'xxxxxxxx' is not found. Billing must be enabled for activation of service(s) 'cloudbuild.googleapis.com,containerregistry.googleapis.com' to proceed.

というようなエラーが出てdeployが失敗するからだ。なんとBilling accountが必要!ということか?

料金プランページを見ると、こうなっている。

https://firebase.google.com/pricing?hl=ja - Firebase Pricing

作業ディレクトリ以下にデフォルトで作られたpackage.jsonを見てみる。

"engines": {
  "node": "10"
},

Node.js 10のバージョン。そして、残念ながらNode 8.jsは非推奨で利用できなくなる方向のようだ。

https://cloud.google.com/functions/docs/concepts/nodejs-8-runtime?hl=ja - Node.js 8 ランタイム

Node.js 10以降に移行して従量課金のBlazeプランを使ってね、ということか。
昔はSpark無料プランでもCloud Functionsを使ってデプロイもOKだったそうだが、これからはBlaze従量課金プランにしろということか。

仕方がないので従量課金プランBlazeにして再デプロイ

初動のテスト学習のために、従量課金はバグったりしてAPIリクエスト叩きすぎたりした時にちょっと嫌だが、“Free up to 2M/month"ということで200万リクエストまでは料金かからないようなので、とりあえず従量課金にした上で、万一バグって料金超過するようなことがないかどうかのアラート通知をオンにして、従量課金のPlazeプランを利用してテストする。

ここで料金プランのところをクリック。

Blazeを選択。

カード情報を登録しているアカウントがあれば、ここで購入。
なければアカウントにカード情報登録する。

HelloWorldくらいでリクエスト大量に誤動作とかはあまりないだろうが、誤動作で課金超過が怖いので、 予算アラートを設定。

これでBlazeプランへの移行は設定完了。

さて、再度deployを実行してみる。

$ firebase deploy --only functions

今度は無事にデプロイできたようだ。

Function URLのところがデプロイされた先のAPIのURLになる。

プロジェクト側のページでも確認できる。

実際にAPIの該当URLを開いてみた結果。

“Hello World!“を無事に表示することができた。

以上、FirebaseのCloud Functionsの機能を使ってHelloWorld的なことはできたが、 Node.jsにもまだあまり詳しくないので、これから少し勉強して何かHugoで作ったサイトを補強する機能をつけたりできないかちょっと検討したいところ。