Firebase用に複数のCloud Functionを作成し、1つのプロジェクトから同時にデプロイしたいと考えています。また、各ファンクションを別のファイルに分けたいと思っています。現在、index.jsに複数の関数を記述することで、以下のように複数の関数を作成することができます。
exports.foo = functions.database.ref('/foo').onWrite(event => {
...
});
exports.bar = functions.database.ref('/bar').onWrite(event => {
...
});
しかし、fooとbarを別々のファイルにしたいと思います。これを試してみました。
/functions
|--index.js (blank)
|--foo.js
|--bar.js
|--package.json
foo.jsがあるところ
exports.foo = functions.database.ref('/foo').onWrite(event => {
...
});
となり、bar.jsは
exports.bar = functions.database.ref('/bar').onWrite(event => {
...
});
すべての関数をindex.jsに入れずに実現する方法はありますか?
あ、FirebaseのCloud Functionsは普通にノードモジュールをロードするので、これは動作します。
構造になっています。
/functions
|--index.js
|--foo.js
|--bar.js
|--package.json
index.jsです。
const functions = require('firebase-functions');
const fooModule = require('./foo');
const barModule = require('./bar');
exports.foo = functions.database.ref('/foo').onWrite(fooModule.handler);
exports.bar = functions.database.ref('/bar').onWrite(barModule.handler);
foo.jsです。
exports.handler = (event) => {
...
};
bar.jsです。
exports.handler = (event) => {
...
};
jasonsirotaさんの回答はとても参考になりました。しかし、特にHTTPトリガー関数の場合は、より詳細なコードを見ることができると便利かもしれません。
jasonsirota'さんの回答と同じ構造を使って、2つの異なるファイルに2つの異なるHTTPトリガー関数を持ちたいとします。
ディレクトリ構造になっています。
/functions
|--index.js
|--foo.js
|--bar.js
|--package.json`
index.jsです。
'use strict';
const fooFunction = require('./foo');
const barFunction = require('./bar');
// Note do below initialization tasks in index.js and
// NOT in child functions:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const database = admin.database();
// Pass database to child functions so they have access to it
exports.fooFunction = functions.https.onRequest((req, res) => {
fooFunction.handler(req, res, database);
});
exports.barFunction = functions.https.onRequest((req, res) => {
barFunction.handler(req, res, database);
});
foo.jsです。
exports.handler = function(req, res, database) {
// Use database to declare databaseRefs:
usersRef = database.ref('users');
...
res.send('foo ran successfully');
}
bar.jsです。
exports.handler = function(req, res, database) {
// Use database to declare databaseRefs:
usersRef = database.ref('users');
...
res.send('bar ran successfully');
}
Update: This doc should help, 私の答えはこのドキュメントよりも古い。
私が個人的にtypecriptでやった方法を紹介します。
/functions
|--src
|--index.ts
|--http-functions.ts
|--main.js
|--db.ts
|--package.json
|--tsconfig.json
前置きが長くなりましたが、この方法を実現するために2つの警告をします。
2.については理由がよくわかりません。2点目は、私の index, main, db の設定を 正確に 尊重してください(少なくとも試してみてください)。
index.ts : エクスポートを扱います。index.tsがexportを扱うようにした方がすっきりします。
// main must be before functions
export * from './main';
export * from "./http-functions";
main.ts : 初期化を扱います。初期化を行います。
import { config } from 'firebase-functions';
import { initializeApp } from 'firebase-admin';
initializeApp(config().firebase);
export * from "firebase-functions";
db.ts: dbを再インポートして、名前がdatabase()
より短くなるようにしただけです。
import { database } from "firebase-admin";
export const db = database();
http-functions.ts
// db must be imported like this
import { db } from './db';
// you can now import everything from index.
import { https } from './index';
// or (both work)
// import { https } from 'firebase-functions';
export let newComment = https.onRequest(createComment);
export async function createComment(req: any, res: any){
db.ref('comments').push(req.body.comment);
res.send(req.body.comment);
}