[javascript] Firebase 용 Cloud Functions를 구성하여 여러 파일에서 여러 기능을 배포하려면 어떻게해야하나요?

Firebase 용 Cloud 기능을 여러 개 만들고 한 프로젝트에서 동시에 모두 배포하고 싶습니다. 또한 각 기능을 별도의 파일로 분리하고 싶습니다. 현재 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에 모든 기능을 넣지 않고이를 수행 할 수있는 방법이 있습니까?



답변

Ah, 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의 답변과 동일한 구조를 사용하여 두 개의 서로 다른 파일에 두 개의 별도 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');
}


답변

업데이트 : 이 문서는 도움이되어야합니다 . 제 답변은이 문서보다 낫습니다.


다음은 타이프 스크립트로 개인적으로 수행 한 방법입니다.

/functions
   |--src
      |--index.ts
      |--http-functions.ts
      |--main.js
      |--db.ts
   |--package.json
   |--tsconfig.json

이 작업을 수행하기 위해 두 가지 경고를 제공하여이 서문을 시작하겠습니다.

  1. index.ts 의 가져 오기 / 내보내기 순서
  2. db는 별도의 파일이어야합니다

포인트 2의 경우 왜 그런지 잘 모르겠습니다. Secundo 당신은 index, main 및 db의 구성을 정확히 존중해야 합니다 (적어도 시도해보십시오).

index.ts : 내보내기를 처리합니다. index.ts가 내보내기를 처리하는 것이 더 깨끗하다는 것을 알았습니다.

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


답변

Cloud / Firebase 기능과 함께 노드 8 LTS를 사용할 수있게되면 스프레드 연산자를 사용하여 다음을 수행 할 수 있습니다.

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


답변

간단하게 유지하기 위해 (하지만 작업을 수행) 개인적으로 코드를 다음과 같이 구성했습니다.

나열한 것

├── /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 답변에 신용


답변

바벨의 경우 / 흐름 은 다음과 같을 것이다 :

디렉토리 레이아웃

.
├── /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 용 Cloud 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 -기능 B

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


답변

bigcodenerd.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메소드에 동일한 패턴이 사용 됩니다.