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


当前回答

@jasonsirota的回答很有帮助。但是查看更详细的代码可能会有用,特别是在HTTP触发函数的情况下。

使用与@jasonsirota回答中相同的结构,假设你希望在两个不同的文件中有两个单独的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'); 
}

其他回答

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

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

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

Export * from './foo';

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

我所做的是根据每个云函数的触发端点将它们组织在单独的文件夹中。每个云函数的文件名都以*.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等似乎更相关的类型的触发器。

这种格式允许您的入口点查找其他函数文件,并自动导出每个文件中的每个函数。

主要入口脚本

找到functions文件夹中的所有.js文件,并导出从每个文件中导出的每个函数。

const fs = require('fs'); const path = require('path'); // Folder where all your individual Cloud Functions files are located. const FUNCTIONS_FOLDER = './scFunctions'; fs.readdirSync(path.resolve(__dirname, FUNCTIONS_FOLDER)).forEach(file => { // list files in the folder. if(file.endsWith('.js')) { const fileBaseName = file.slice(0, -3); // Remove the '.js' extension const thisFunction = require(`${FUNCTIONS_FOLDER}/${fileBaseName}`); for(var i in thisFunction) { exports[i] = thisFunction[i]; } } });

从一个文件导出多个函数

Const functions = require('firebase-functions'); Const query = functions.https。onRequest((req, res) => { Let query = req.query.q; res.send ({ “You searching For”:查询 }); }); const searchTest = functions.https。onRequest((req, res) => { res.send ({ "searchTest": "你好!" }); }); 模块。出口= { 查询 searchTest }

HTTP可访问端点有适当的命名

✔功能:查询:http://localhost:5001/PROJECT-NAME/us-central1/query function: helloWorlds: http://localhost:5001/PROJECT-NAME/us-central1/helloWorlds ✔功能:searchTest: http://localhost:5001/PROJECT-NAME/us-central1/searchTest

一个文件

如果你只有几个额外的文件(例如只有一个),你可以使用:

Const your_functions = require('./path_to_your_functions'); For (var I in your_functions) { export [i] = your_functions[i]; }

@jasonsirota的回答很有帮助。但是查看更详细的代码可能会有用,特别是在HTTP触发函数的情况下。

使用与@jasonsirota回答中相同的结构,假设你希望在两个不同的文件中有两个单独的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'); 
}

以上的答案为我指明了正确的方向,只是没有一个真正适合我。下面是一个工作原型,一个onCall, onRequest和数据库触发器的例子

foo.js - 随叫随到,随叫随到。

exports.handler = async function(data, context, admin) {
    // const database = admin.database();
    // const firestore = admin.firestore();
    //...
};

bar.js - onRequest

exports.handler = async function(req, res, admin) {
    // const database = admin.database();
    // const firestore = admin.firestore();
    //...
};

jar.js - trigger/document/onCreate .js

exports.handler = async function(snapshot, context, admin) {
    // const database = admin.database();
    // const firestore = admin.firestore();
    //...
};

index.js

//导入firebase管理SDK依赖项

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

// import functions
const foo = require("./foo");
const bar = require("./bar");
const jar = require("./jar");

// onCall for foo.js
exports.foo = functions.https.onCall((data, context) => {
    return foo.handler(data, context, admin);
});

// onRequest for bar.js
exports.bar = functions.https.onRequest((req, res) => {
    return bar.handler(req, res, admin);
});

// document trigger for jar.js
exports.jar = functions.firestore
  .document("parentCollection/{parentCollectionId}")
  .onCreate((snapshot, context) => {
    return jar.handler(snapshot, context, admin);
});

注意:你也可以创建一个子文件夹来存放你的各个函数