GoogleのFirebaseが面白いかもしれない 〜Functions〜

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
ファンクション!!

この記事を三行にまとめると

くしゃみ連発ファンクション!!
ここまでやれれば基本はだいぶ押さえられると思います
使いこなせればかなりいろんなことができるっぽいです
寒い日が続いておりますがみなさんは風邪など引いてないでしょうか? 僕は風邪は引いてませんが鼻炎持ちなこともあってここ最近は鼻水がよく出ます。特に夜冷え込むとやたらと出やすくなりますね。くしゃみ連発ファンクション!!

そんなわけで今日はFirebaseのファンクションを使ってみたいと思います。今までホスティングやらデータベースやらストレージやらいくつかの機能を扱ってきましたが、ここまでやれれば基本はだいぶ押さえられると思います。

ではいざ。



プロジェクトの開始

以下のコマンドをターミナルなどで入力すればオッケーです。

$ firebase init functions

いくつか質問されますが、何も考えずにyesを選択しておけば問題ないと思います。無事にinitが完了したら「functions」というフォルダができているはずです。

ホスティングと合わせるとこんな感じのフォルダ構成になってると思う。

/firebase
  ├ /public
  │   └ index.html
  ├ /functions
  │   ├ index.js
  │   ├ package.json
  │   └ /node_modules
  └ firebase.json

「node_modules」フォルダの中に関してはここでは省略します。Node.jsに関するファイルがいろいろと入ってますが、数が多いので。

これで準備ができました。



関数の作成

では実際に関数を作ってみます。

関数はindex.jsの中に作成します。といってもinitした時点でindex.jsの中にはサンプルコードみたいなのができてるんで、まずはそれ使わせてもらいましょう。

index.jsを開くとこんな感じのコードがあると思います。

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

これは画面上に「Hello from Firebase!」と表示する関数です。

これをデプロイする。

$ firebase deploy

無事にデプロイが完了すれば、以下のURLにアクセスすると「Hello from Firebase!」が表示されます。

https://us-central1-norm-nois.cloudfunctions.net/helloWorld

URLの中の「norm-nois」っていうのはプロジェクトIDです。僕の場合はnorm-noisですが、そこは各々のプロジェクトに合わせて変更してください。

index.jsの二行目に「exports.helloWorld」というのがありますが、この「helloWorld」というのがURLに関わってきます。ここを任意に変えればURLも任意に変わる。「exports.***」と「https://us-central1-{プロジェクトID}.cloudfunctions.net/***」が対応してる感じ。

ちなみに上のコードでデプロイすると、ホスティングなども一緒にデプロイされます。今回ホスティングは特にいじってないので、毎回一緒にデプロイする必要はない。そういうときは「only」というオプションを使ってfunctionsだけデプロイすることもできます。

$ firebase deploy --only functions



デプロイできない場合

もしもこんなエラーが出てデプロイできない場合。

Deploy Error: Function load error: Code in file index.js can’t be loaded.

Error: Cannot find module ‘firebase-admin’

僕は最初このエラーが出てデプロイできませんでした。おそらく「firebase-functions」や「firebase-admin」のバージョンに問題があってデプロイできないんだと思います。

エラーを解決するためにいろいろこねくり回してしまったんで、最終的にどのバージョンにすれば正解だったのかがよく分からないんですけど、僕は以下のバージョンに変更したら動くようになりました。

firebase-functions・・・latest
firebase-admin・・・5.4.2

latestってのは現時点での最新バージョンです。この記事を書いてる時点では0.7.5くらいかな?

ということで、node_modulesフォルダの中にあるfirebase-functionsやfirebase-adminのバージョンを変更します。

$ npm install --save-exact firebase-functions@latest
$ npm install --save-exact firebase-admin@5.4.2

次にfunctionsフォルダの中にあるpackage.jsonを書き換える。

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "dependencies": {
    "firebase-admin": "5.4.2",
    "firebase-functions": "latest"
  },
  "private": true
}


たぶんこれだけでも大丈夫だと思うのですが、こちらのページを見ると、functionsはNode.jsのバージョンが6.11.5を実行するとあります。

エラーが出た段階で僕の使ってたNode.jsはバージョンが6.3くらいだったので、一応Node.jsのバージョンも上げておきました。

バージョンを変更する方法はいくつかありますが、僕はnコマンドを使いました。

$ npm install -g n
$ n 6.11.5

一行目がnコマンドのインストール、二行目でNode.jsのバージョンを6.11.5にしています。



ホスティングURLで関数を呼び出す

先ほど作成した関数を、ホスティングの方のURLに対応させることができます。

ここでは「https://norm-nois.firebaseapp.com/hello」というURLでhelloWorldの関数を呼び出せるようにしてみましょう。

URLの作成はホスティングの回にやったfirebase.jsonにリライトルールを書くことで実現できます。

{
  "hosting": {
    "public": "public",
    "rewrites": [
      {
        "source": "/hello",
        "function": "helloWorld"
      }
    ]
  }
}

これでオッケーです。これでデプロイすれば以下のURLで「Hello from Firebase!」が表示されるようになる。

https://norm-nois.firebaseapp.com/hello



関数の削除

パッと見コンソール画面とかには関数を削除するような機能が見当たらないので、不要になった関数を削除する場合は、index.jsから該当のコードを削除するなりコメントアウトするなりしてデプロイする必要があるみたいです。そのうちコンソール画面などからも削除できるようになるかもしれません。

ちなみにFunctionsにはhttpsだけでなく、例えばデータベースの更新やファイルのアップロードをトリガーにして何からの処理を追加したりとかもできるのですが、同一の関数を他のトリガーに変更する場合は一度関数を削除してから書き直さないとエラーになることがあるみたいです。

例えば先ほどの「helloWorld」をCloud Firestoreの何かしらのトリガーに変更した場合。

//変更前
exports.helloWorld = functions.https.onRequest((request, response) => {
 response.send("Hello From Firebase!");
});

//変更後
exports.helloWorld = functions.firestore.document('users/1').onWrite((event) => {
  //何らかの処理
});

このままデプロイすると以下のようなエラーが出ます。

HTTP Error: 400, Change of function trigger type or event provider is not allowed

このエラーが出た時は一度変更前のhelloWorldを削除するかコメントアウトしてデプロイした後、変更後のコードを書いて再びデプロイすれば正常にデプロイが完了します。onWrite()を同じFirestoreの他のトリガー(onUpdate()とか)に変更する場合だったら削除しなくても大丈夫です。






外部とのAPI連携みたいなこともできれば良かったのですが、どうやら無料プランの場合、Functionsは外部へのアクセスができないみたいです。なのでそれについては今回は断念。残念。

あと画面に「Hello!」と表示するだけじゃなくてもう少しいろいろやってそれを紹介できたら良かったのですが、何かあまり上手くできなくて……例えば「/users/:id」で動的にIDを取得したりとか。なのでその辺も今回は断念です。残念です。

データベースなどのトリガーについても今回はやりませんでしたが、できることは多いみたいなので、使いこなせればかなりいろんなことができるっぽいです。



その他のFirebaseに関する記事はこちら

 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください