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


当前回答

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

布局

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

foo.ts

export const fooFunction = functions.database()......... {
    //do your function.
}

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

bar.ts

export const barFunction = functions.database()......... {
    //do your function.
}

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

index.ts

import * as fooFunctions from './foo';
import * as barFunctions from './bar';

module.exports = {
    ...fooFunctions,
    ...barFunctions,
};

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

其他回答

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

主要入口脚本

找到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]; }

在Babel/Flow的情况下,它看起来像这样:

目录布局

.
├── /build/                     # Compiled output for Node.js 6.x
├── /src/                       # Application source files
│   ├── db.js                   # Cloud SQL client for Postgres
│   ├── index.js                # Main export(s)
│   ├── someFuncA.js            # Function A
│   ├── someFuncA.test.js       # Function A unit tests
│   ├── someFuncB.js            # Function B
│   ├── someFuncB.test.js       # Function B unit tests
│   └── store.js                # Firebase Firestore client
├── .babelrc                    # Babel configuration
├── firebase.json               # Firebase configuration
└── package.json                # List of project dependencies and NPM scripts

src/index.js -主要导出

export * from './someFuncA.js';
export * from './someFuncB.js';

src/db.js - Postgres云SQL客户端

import { Pool } from 'pg';
import { config } from 'firebase-functions';

export default new Pool({
  max: 1,
  user: '<username>',
  database: '<database>',
  password: config().db.password,
  host: `/cloudsql/${process.env.GCP_PROJECT}:<region>:<instance>`,
});

src/store.js - Firebase Firestore客户端

import firebase from 'firebase-admin';
import { config } from 'firebase-functions';

firebase.initializeApp(config().firebase);

export default firebase.firestore();

src/someFuncA.js -函数A

import { https } from 'firebase-functions';
import db from './db';

export const someFuncA = https.onRequest(async (req, res) => {
  const { rows: regions } = await db.query(`
    SELECT * FROM regions WHERE country_code = $1
  `, ['US']);
  res.send(regions);
});

src/someFuncB.js

import { https } from 'firebase-functions';
import store from './store';

export const someFuncB = https.onRequest(async (req, res) => {
  const { docs: regions } = await store
    .collection('regions')
    .where('countryCode', '==', 'US')
    .get();
  res.send(regions);
});

.babelrc

{
  "presets": [["env", { "targets": { "node": "6.11" } }]],
}

firebase.json

{
  "functions": {
    "source": ".",
    "ignore": [
      "**/node_modules/**"
    ]
  }
}

package.json

{
  "name": "functions",
  "verson": "0.0.0",
  "private": true,
  "main": "build/index.js",
  "dependencies": {
    "firebase-admin": "^5.9.0",
    "firebase-functions": "^0.8.1",
    "pg": "^7.4.1"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-jest": "^22.2.2",
    "babel-preset-env": "^1.6.1",
    "jest": "^22.2.2"
  },
  "scripts": {
    "test": "jest --env=node",
    "predeploy": "rm -rf ./build && babel --out-dir ./build src",
    "deploy": "firebase deploy --only functions"
  }
}

$ yarn install                  # Install project dependencies
$ yarn test                     # Run unit tests
$ yarn deploy                   # Deploy to Firebase

org大纲是一个更简单的体系结构模式,可以将方法分离到不同的文件中,并在index.js文件中的一行中导出。

本示例中项目的架构如下:

projectDirectory

index.js podcast.js profile.js

index.js

const admin = require('firebase-admin');
const podcast = require('./podcast');
const profile = require('./profile');
admin.initializeApp();

exports.getPodcast = podcast.getPodcast();
exports.removeProfile = profile.removeProfile();

podcast.js

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

exports.getPodcast = () => functions.https.onCall(async (data, context) => {
      ...
      return { ... }
  });

同样的模式将用于概要文件中的removeProfile方法。

以上的答案为我指明了正确的方向,只是没有一个真正适合我。下面是一个工作原型,一个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);
});

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

在我努力实现@zaidfazil的解决方案时,我想出了以下方法(使用JavaScript,而不是TypeScript)。

multi.js

exports.onQuestionMultiCreate = functions.database
  .ref("/questions-multi/{questionId}")
  .onCreate(async (snapshot, context) => {
   ...
    }
  });

trueFalse.js

exports.onQuestionTrueFalseCreate = functions.database
  .ref("/questions-truefalse/{questionId}")
  .onCreate(async (snapshot, context) => {
   ...
    }
  });

index.js


const multi = require("./multi");
const trueFalse = require("./trueFalse");

module.exports = {
  ...multi,
  ...trueFalse