我想为Firebase创建多个云功能,并从一个项目同时部署它们。我还想将每个函数分离到一个单独的文件中。目前,我可以创建多个函数,如果我把它们都放在index.js,如:

exports.foo = functions.database.ref('/foo').onWrite(event => {
    ...
});

exports.bar = functions.database.ref('/bar').onWrite(event => {
    ...
});

然而,我想把foo和酒吧在单独的文件。我试了一下:

/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中的情况下实现这一点?


当前回答

有一种很好的方法可以长期组织所有的云功能。我最近就这么做了,效果完美无缺。

我所做的是根据每个云函数的触发端点将它们组织在单独的文件夹中。每个云函数的文件名都以*.f.js结尾。例如,如果你在user/{userId}/document/{documententid}上有onCreate和onUpdate触发器,那么在functions/user/document/目录下创建两个文件onCreate.f.js和onUpdate.f.js,你的函数将分别命名为userDocumentOnCreate和userDocumentOnUpdate。(1)

下面是一个目录结构示例:

functions/
|----package.json
|----index.js
/----user/
|-------onCreate.f.js
|-------onWrite.f.js
/-------document/
|------------onCreate.f.js
|------------onUpdate.f.js
/----books/
|-------onCreate.f.js
|-------onUpdate.f.js
|-------onDelete.f.js

样本函数

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const db = admin.database();
const documentsOnCreate = functions.database
    .ref('user/{userId}/document/{documentId}')
    .onCreate((snap, context) => {
        // your code goes here
    });
exports = module.exports = documentsOnCreate;

Index.js

const glob = require("glob");
const camelCase = require('camelcase');
const admin = require('firebase-admin');
const serviceAccount = require('./path/to/ServiceAccountKey.json');
try {
    admin.initializeApp({ credential: admin.credential.cert(serviceAccount),
    databaseURL: "Your database URL" });
} catch (e) {
    console.log(e);
}

const files = glob.sync('./**/*.f.js', { cwd: __dirname });
for (let f = 0, fl = files.length; f < fl; f++) {
    const file = files[f];
    const functionName = camelCase(file.slice(0, -5).split('/')); 
    if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === functionName) {
        exports[functionName] = require(file);
      }
}

你可以使用任何你想要的名字。对我来说,onCreate.f.js, onUpdate.f.js等似乎更相关的类型的触发器。

其他回答

Node 8 LTS现在可以与Cloud/Firebase函数一起使用,您可以使用扩展操作符执行以下操作:

/ package.json

"engines": {
  "node": "8"
},

/ index.js

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

module.exports = {
  ...require("./lib/foo.js"),
  // ...require("./lib/bar.js") // add as many as you like
};

/lib/foo.js

const functions = require("firebase-functions");
const admin = require("firebase-admin");

exports.fooHandler = functions.database
  .ref("/food/{id}")
  .onCreate((snap, context) => {
    let id = context.params["id"];

    return admin
      .database()
      .ref(`/bar/${id}`)
      .set(true);
  });

啊,Firebase负载节点模块的云函数通常,所以这是有效的

结构:

/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) => {
    ...
};

为了保持简单(但能完成工作),我个人是这样构造我的代码的。

布局

├── /src/                      
│   ├── index.ts               
│   ├── foo.ts           
│   ├── bar.ts
|   ├── db.ts           
└── package.json  

foo.ts

import * as functions from 'firebase-functions';
export const fooFunction = functions.database()......... {
    //do your function.
}

export const someOtherFunction = functions.database().......... {
    // do the thing.
}

bar.ts

import * as functions from 'firebase-functions';
export const barFunction = functions.database()......... {
    //do your function.
}

export const anotherFunction = functions.database().......... {
    // do the thing.
}

db.ts

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';

export const firestore = admin.firestore();
export const realtimeDb = admin.database();

index.ts

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';

admin.initializeApp(functions.config().firebase);
// above codes only needed if you use firebase admin

export * from './foo';
export * from './bar';

适用于任何嵌套级别的目录。也只需遵循目录中的模式即可。

这要归功于@zaidfazil的答案

如果您正在使用typescript创建云函数,这里有一个简单的答案。

/functions
|--index.ts
|--foo.ts

几乎所有在顶部的常规导入都是从foot .ts导出所有函数。

Export * from './foo';

Firebase文档现在已经更新了一个多文件代码组织的好指南:

文档>云功能>写功能>组织功能

总结:

foo.js

const functions = require('firebase-functions');
exports.foo = functions.https.onRequest((request, response) => {
  // ...
});

bar.js

const functions = require('firebase-functions');
exports.bar = functions.https.onRequest((request, response) => {
  // ...
});

index.js

const foo = require('./foo');
const bar = require('./bar');
exports.foo = foo.foo;
exports.bar = bar.bar;