firebase functions で関数をファイル分割してメンテナンス性を高める【javascript】

投稿者: | 2019年8月23日

はじめに

firebaseのfunctionsですが普通にやると全ての関数をindex.jsに書くことになるので、規模が大きくなってくるとメンテナンスが大変になっていきます。そこで関数ごとにファイル分割しようよという話です。以下の記事を参考にやってみました。

また、firebase functionsではJavascriptとTypescriptを選択できますが、私はJavascriptを利用しています。

参考にした記事

コード

今回の関数の仕様

実際に開発中のサービスのコードです。

  • func1  食品(food)に対して投稿(post)が入ったときに投稿数をインクリメントしてfirestoreに書き戻す
  • func2  投稿(post)に対してコメントが入ったときに、コメント数をインクリメントしてfirestoreに書き戻す

ソースコード

index.js

const functions = require('firebase-functions');
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
const db = admin.firestore()
const settings = {timestampsInSnapshots: true};
db.settings(settings);

// func1
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'func1') {
  exports.onPost = require('./funcs/func1')(db);
}

// func2
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'func2') {
  exports.onPostComment = require('./funcs/func2')(db);
}
  • ifでprocess.envを見ているのは、こうすることで特定の関数を呼ばれた際に、ロードする量を関数のみに限定できるから(だそうです)。詳細は参考リンクを見てみてください。
  • index.jsではfirebaseの初期化と関数の呼び出しをやってます。
  • 関数の呼び出しの際に、require(functionPath)(db)とすることで、呼び出している関数に引数を渡せます。ここでは初期化したfirebase.firestoreを渡している形です。
  • ※呼び出し先の関数側でfirestoreの初期化をすることもできるのですが、それだと何回も初期化が走ることになり、firebase deploy時にデプロイエラーとなりました…

func1.js

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

module.exports = (db) => functions.region('asia-northeast1').firestore
  .document('post/{postId}')
  .onCreate((snap, context) => {
    let newPost = snap.data()
    let foodId = newPost.food.id

    db.collection('food').doc(foodId).get()
      .then(doc => {
        let foodData = doc.data()
        if (foodData.postCount) {
          foodData.postCount++
        } else {
          foodData.postCount = 1
        }
        db.collection('food').doc(foodId).set({
          postCount: foodData.postCount
        }, {merge: true})
          .then(function (){
            return console.log("successfully count postCount")
          })
      })
  })
  • module.exports = (db) =>とすることで、index.jsで引数に設定したdbを受け取って動作します
  • functions.region(‘asia-northeast1’)とすることで、functionsの動作するリージョンを指定できます。アジアを選択しときましょう。
  • あとは普通のfirestore更新トリガの処理を書くだけです。

func2.js

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

// 投稿へのコメント投稿時のアクション
module.exports = (db) => functions.region('asia-northeast1').firestore
  .document('post/{postId}/comment/{commentId}')
  .onCreate((snap, context) => {
    let newPost = snap.data()
    let postId = context.params.postId

    db.collection('post').doc(postId).get()
      .then(doc => {
        let post = doc.data()
        if (post.commentCount) {
          post.commentCount++
        } else {
          post.commentCount = 1
        }
        db.collection('post').doc(postId).set({
          commentCount: post.commentCount
        }, {merge: true})
          .then(function (){
            return console.log("successfully count post.commentCount")
          })
      })
  })
  • func1と同じですね

おわり

こんな感じで上手くいきました。

久々に記事書いたけど、こんな手抜きでも大変だなぁ…


カツオが開発したWebサービスです。

「セールサーチ」ネットショップのセール情報の検索サイト!

平成の想い出を気軽に年表にしてシェアすることができるサービスです。ぜひ使ってみてください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です