世界一簡単なCloud Functions For Firebase入門
概要
これまで、自分はサーバーレス(AWS LamndaやCloud Functions For Firebase)という技術について触ったことがなく、どんなことができるかもいまいち知り得ないという状態でした。
そこで今回、軽く入門してみようと思い、簡易的なAPIの開発を通じて勉強していこうと思います。
今回のAPIの開発は専用のリポジトリを作成していますので、よかったら参考にしてみてください!
専用のリポジトリ
今回やることは、大まかに以下の通りです。
- firebaseのプロジェクトを新規開設
- 必要なライブラリをインストールし、セットアップを行う
- cloud functionsで何らかの値をレスポンスとして返してくれるエンドポイントを実装
- firebase deployする
上記の一連の流れとは別に、追加でfirestoreへのデータの追加・読み出しを行うAPIの実装なども行っていきたいと思ってます。
また、今後追加でfirestoreと連携させ、firestoreに格納されたデータなどをjson形式で返してくれるエンドポイントなんかも取り入れようと思っています。
コンソールからFirebaseのプロジェクトを作成する
プロジェクト名を決める
下記のプロジェクトを新規作成する画面で、何らかのプロジェクト名を入力して下さい。
今回、cloud functionのチュートリアルということで、自分はcloud-function-tutorial
と名付けました。
名前の入力が完了したら、そのまま「続行」のボタンをクリックします。
Google Analyticsの設定をする
今回のプロジェクトではGoogle Analyticsを使用する予定はありませんので、有効のチェックを外していただいて大丈夫です。
最後に「プロジェクトを作成」するボタンをクリックいただくと、プロジェクトの作成が行われます。
下記のようにプロジェクトのダッシュボードの画面に遷移したら、無事プロジェクトの作成は完了です。
必要なライブラリ等のインストールおよびセットアップを行う
今回、cloud functionをいじる際に必要なライブラリや実行環境は下記の通りです。
- Node.js
- npm
- firebase-tools
firebase-toolsというライブラリに関して
cliでfirebaseを使うのに必要になります。
こちらをインストールすることで、firebase
コマンドが使えるようになり、様々なことがcliでできるようになります。
今回は、npm
とNode.js
はインストール済みという前提で進めさせていただきます!🙇♂️
firebase-toolsをインストールする
下記のコマンドを実行して、firebase-toolsというライブラリをインストールします。
$ npm install -g firebase-tools
下記のように、firebase
コマンドが実行できたらOKです。
$ firebase --version
11.0.0
cliからfirebaseにログインする
クラウド上のfirebaseのアカウントとローカルのcli上のfirebaseとを紐づけるために、cliからfirebaseにログインします。
下記のコマンドでログインします。
$ firebase login
※ログイン時に下記のような質問があると思いますが、n(No)
でOKです!
これはただのFirebaseがCLIの使用状況とエラーレポート情報を収集できるようにするかどうかの確認なのでNoで大丈夫です。
? Allow Firebase to collect CLI usage and error reporting information?
firebaseのプロジェクトの初期化を行う
$ firebase init firestore
$ firebase init functions
上記の二つのコマンドを実行して、プロジェクトの初期化を行います。
この二つのコマンドをどちらも実行時にいくつかの質問に答えつつ、進めていってください。
基本的には、useing a exists project
(文言あってなかったらごめんなさい)みたいなやつを選んでいただければOKです!
そちらを選ぶと、実際に既存のプロジェクトの中からどのプロジェクトを使用するか聞かれるので、先ほど作ったばかりのプロジェクトを選択してください。
またFunctionsの方では、Functionsに記述する言語をJavaScript
かTypeScript
のどちらにするか質問されると思います。
今回のチュートリアルは、「世界一簡単」を目指していきたいのでJavaScript
を選択します。
上記の二つのコマンドの両方とも、下記のような文言が表示されれば初期化が無事完了したことになります。
✔ Firebase initialization complete!
実際にAPIのエンドポイントを実装する
この段階で、ディレクトリ構成は下記のようになっています。
$ tree .
.
├── .firebaserc
├── .gitignore
├── README.md
├── firebase.json
├── firestore.indexes.json
├── firestore.rules
└── functions
├── .eslintrc.js
├── .gitignore
├── index.js
└── package.json
このtree構造の中のfunctions/index.js
というファイルに実際のAPIのエンドポイントとなる関数を実装していきます。
今の時点では、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) => {
// functions.logger.info("Hello logs!", {structuredData: true});
// response.send("Hello from Firebase!");
// });
まずは、デフォルトで表記されているエンドポイントのサンプルコードを動かしてみたいと思います。
こちらのコメントになっている部分のコメントを外して下記のように書き換えます。
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!");
});
次にfunctionsディレクトリに移動し、firebaseのemulatorsを起動します。
$ cd functions
$ npm run serve
下記のような画面になれば、無事起動完了です。
こちらのエンドポイントをcurl
コマンドを叩いてみます。
※ helloWorld
はfunctionの名前です。
$ curl http://localhost:5001/${プロジェクトID}/${リージョン}/helloWorld
このコマンドの結果として、Hello from Firebase!
という文字列が表示されれば成功です。
firebase deployする
一旦ここまでで、このfunctionをデプロイしてみたいと思います。
デプロイに際して、下記のコマンドを実行してください。
$ firebase deploy --only functions
このコマンドを実行すると、下記のようなエラーメッセージが表示されるかと思います。
【Firebase】Cloud Functionsが従量課金プランでしか使えなくなるらしいというこちらの記事によると、どうやら
要約するとこんな感じ
- Cloud FunctionsがNode.js 10になってNode.js 8が非推奨になるよ
- いまNode.js 8使ってる人はアップデートしてね
- Node.js 10はBlaza(従量課金)プランでしか使えないからSpark(無料)プラン使ってる人はアップデートしてね
ってことらしい
とのことらしいです。
ということで、コンソールからFunctionsのプランをSpark
からBlaze
にアップグレードしてください。
無料枠分はちゃんと適応されるぽいので、よっぽどのことがない限りはお金の支払いが発生することはないでしょう。
再度、上記のデプロイコマンドを実行してみてください。
✔ Deploy complete!
このような文言が出力されれば、無事デプロイ完了です。
firestoreへのデータの追加・読み出しをするAPIを作ってみる
テストデータを用意する
今回は、まずIDがtest
というcollectionを作成して、そのcollectionが存在していることを前提に進めていこうと思います。
※最初のこちらのcollectionと、初期データのに手動で作成いただくことになります。
初期データには、id
フィールドとname
フィールドを作成して任意の値を設定してください。
admin sdkからfirestoreを使えるように設定する
const admin = require("firebase-admin");
// Admin SDKでfireStoreを使う
admin.initializeApp(functions.config().firebase);
// データベースの参照を取得する
const fireStore = admin.firestore();
firestoreからデータを取得して返すエンドポイントを実装する
以下は実装は、firestoreのtest
というcollectionから任意のdocument IDのドキュメントのデータを取得して、レスポンスとしてクライアントに返すというエンドポイントです。
exports.getFirestore = functions.https.onRequest((req, res) => {
// パラメータを取得
const params = req.body;
// パラメータから任意のdocument IDを取得する
const documentId = params.documentId;
if (documentId) {
// 'test'というcollectionの中の任意のdocumentに格納されているデータを取得する
const testRef = fireStore.collection('test');
testRef.doc(documentId).get().then((doc) => {
if (doc.exists) {
res.status(200).send(doc.data());
} else {
res.status(200).send("document not found");
}
});
} else {
res.status(400).send({errorMessaage: 'document id not found'});
}
});
以下のcurlコマンドを実行して、エンドポイントを確認してみてください。
$ curl http://localhost:5001/${プロジェクトID}/${リージョン}/getFirestore --data 'documentId=${任意のdcument ID}'
firestoreのcollectionに任意のIDのドキュメントを作成するエンドポイントを実装する
以下の実装は、任意のデータ(パラメータ)を渡すとそれをfirestoreの任意のIDのdocumentを作成しデータを格納したのち、格納したデータをレスポンスとして返すというエンドポイントです。
// 渡されたパラメータのスキーマをチェックする
const validateParamsSchema = (params) => {
const hasId = 'id' in params;
const hasName = 'name' in params;
const hasDocumentId = 'documentId' in params;
return hasId && hasName && hasDocumentId;
};
// firestoreに任意のデータを保存する
exports.saveFirestore = functions.https.onRequest((req, res) => {
const params = req.body;
// パラメータのスキーマのチェック
if (!validateParamsSchema(params)) {
res.status(400).send({errorMessaage: 'パラメータが不正です'});
} else {
const db = fireStore;
// 'test'というcollectionがある前提で任意のドキュメントIDのdocumentを生成する
db.doc(`test/${params.documentId}`).set({
id: params.id,
name: params.name,
});
// 非同期的に保存したデータを参照する
db.collection('test')
.doc(params.documentId)
.onSnapshot((doc) => {
// 取得したデータをレスポンスとして返す
res.status(200).send(doc.data());
});
}
});
こちらに関しても同様に、以下のコマンドでエンドポイントの確認をしてみてください。
各パラメータの値は任意の値でOKです。
curl http://localhost:5001/${プロジェクトID}/${リージョン}/saveFirestore --data 'id=7&name=test 7&documentId=custome doc7'
再度、firebaseをdeployする
下記のコマンドを実行して、firestoreとcloud functionsをdeployします。
$ firebase deploy --only functions
$ firebase deploy --only firestore
deployが成功したら、以上で本チュートリアルは終了になります。
お疲れ様でした。
何か不明点などがあればコメントを頂けますと幸いです。
Discussion
記事を拝見させていただきました。
初心者の僕でもdeployを成功させることができました。
いろいろ調べてみたのですが、わからないことがいくつかあったので質問させていただきます。
npm run serveのコマンド実行後
npm run serveのコマンド実行後
curl http://localhost:5001///saveFirestore --data 'id=7&name=test%207&documentId=custom%20doc7'
と打ってみたのですが、エンターを押しても反応がなく(ただ改行されるだけ)、テスト試行ができませんでした。npm run serveの扱いについて調べてみたのですが、有益な情報は得られませんでした。
jsコードの実行タイミング
jsコードを使ってfirestoreの情報を更新したり、取得することが可能なのはわかりましたが、問題はjsファイルをdeployした後、どのタイミングでコードが実行されるのかということです。deploy直後に一度だけ実行されるのでしょうか?
素人質問で誠に恐縮ですが、返信くださると大変助かります。