Как структурировать облачные функции для Firebase для развертывания нескольких функций из нескольких файлов?

164

Я хотел бы создать несколько облачных функций для Firebase и развернуть их одновременно из одного проекта. Я также хотел бы разделить каждую функцию в отдельный файл. В настоящее время я могу создать несколько функций, если я помещу их обе в 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?

jasonsirota
источник
1
@JPVentura. На самом деле не понимаю вас хорошо. Пожалуйста, объясни.
HuyLe
Это было обновлено для v1.0? У меня проблемы: stackoverflow.com/questions/50089807/…
tccpg288
2
К вашему сведению, этот официальный пример функций Firebase содержит несколько .jsфайлов, импортированных через require: github.com/firebase/functions-samples/tree/master/…
xanderiel
Это может быть полезно: stackoverflow.com/questions/43486278/…
Ramesh-X

Ответы:

126

Ах, Cloud Functions для 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) => {
    ...
};
jasonsirota
источник
1
Могу ли я, например, иметь несколько функций в модуле foo? Если так, как это лучше реализовать?
Александр Хитев
1
Я полагаю, вы могли бы и назначить разные обработчики для разных экспортируемых функций из foo: exports.bar = functions.database.ref ('/ foo'). OnWrite (fooModule.barHandler); exports.baz = functions.database.ref ('/ bar'). onWrite (fooModule.bazHandler);
Jasonirota
44
Мне не нравится это решение, потому что оно перемещает информацию (а именно пути к базам данных) из foo.js и bar.js в index.js, что в некоторой степени лишает смысла иметь эти отдельные файлы.
бв
Я согласен с @bvs, думаю, у Седа хороший подход. Я собираюсь немного изменить его, явно экспортировав каждый модуль, чтобы сделать index.ts супер ясным, например, export {newUser} из "./authenticationFunctions"
Alan
2
Я думаю, что мой первоначальный вопрос был просто о развертывании нескольких функций в одном проекте без помещения функций в файл index.js, где и как вы передаете информацию базы данных, это не входит в сферу действия. Если бы это был я, я бы, вероятно, создал бы отдельный модуль, который контролировал бы доступ к базе данных и требовал бы этого в foo.js и bar.js отдельно, но это стилистическое решение.
jasonsirota
75

Ответ @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'); 
}
Студент колледжа
источник
Текущая структура в index.js не сработала для меня. Мне нужно было сначала импортировать модули Firebase, затем инициализировать приложение и затем импортировать функции из других папок. Таким образом, мое приложение сначала инициализирует, аутентифицирует, что угодно, а затем импортирует функции, которые требуют предварительной инициализации приложения.
Тонкатата
47

Обновление: этот документ должен помочь , мой ответ старше этого документа.


Вот как я лично сделал это с машинописью:

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

Позвольте мне предварить это, дав два предупреждения, чтобы сделать эту работу:

  1. порядок импорта / экспорта имеет значение в index.ts
  2. БД должен быть отдельным файлом

Для пункта № 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 : просто переэкспортируйте базу данных, чтобы ее имя было короче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);
}
CED
источник
как выглядит ваш tsconfig? Как я могу скомпилировать в папку dist и сообщить функциям gcloud, где находится мой index.js? У вас есть код на github? :)
Берлинг
@ choopage-JekBao извините, это было давно, у меня больше нет проекта. Если я правильно помню, вы можете указать каталог конфигурации firebase (по умолчанию общедоступный). Хотя я могу ошибаться, так как прошло больше года
Сед
Привет @ced - почему содержимое не может db.tsвойти внутрь main.ts(после создания администратора?). Или вы только что раскололись для ясности / простоты?
DSG38
1
@ dsg38 это было опубликовано слишком давно, я действительно не понимаю, почему это должно быть в отдельном файле, глядя на ответ сейчас .. Я думаю, что это было для ясности
Ced
21

С Node 8 LTS, который теперь доступен с Cloud / Firebase Functions, вы можете сделать следующее с помощью операторов распространения:

/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);
  });
Люк Пигетти
источник
Интересно, замедляется ли рост числа импортов при холодном запуске каждой функции или же должно быть много отдельных модулей, разработанных отдельно?
Симон Факир
2
я получаю ошибку расставания eslint unexpected token ...внутри index.js.
томас
Возможно, вы не используете Node 8
Luke Pighetti
@SimonFakir хороший вопрос. Вы нашли что-нибудь об этом?
атерешков
@atereshkov да Я нашел способ загрузить только запрошенную функцию, включая ее зависимости, используя «process.env.FUNCTION_NAME», как ответ ниже. Я также могу поделиться своим репо в качестве ссылки, если вы заинтересованы, свяжитесь со мной.
Саймон Факир
16

Чтобы быть простым (но делает работу), я лично структурировал свой код следующим образом.

раскладка

├── /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 ответ

Реза
источник
1
Это один из самых простых ответов для Typescript, спасибо. Как вы справляетесь, например, с одним экземпляром базы данных firebase? admin.initializeApp(functions.config().firestore) const db = admin.firestore();Куда вы кладете это и как относитесь к нему в foo и bar?
elprl
Эй, почему содержимое не может db.tsвойти внутрь index.ts(после создания администратора?). Или вы только что раскололись для ясности / простоты?
DSG38
1
@ dsg38 вы можете смешать все вместе, это проясняет
Реза
Я сделал нечто подобное для TS, спасибо, это простое и хорошее решение
Рубен
10

В случае с 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 - Облачный SQL-клиент для Postgres

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 Client

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

firebase.initializeApp(config().firebase);

export default firebase.firestore();


src/someFuncA.js - функция А

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
Константин Таркус
источник
9

Схема 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метода в файле профиля .

Адам Гурвиц
источник
7

Чтобы быть простым (но делает работу), я лично структурировал свой код следующим образом.

раскладка

├── /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,
};

Работает для каталогов любых вложенных уровней. Просто следуйте шаблону внутри каталогов тоже.

zaidfazil
источник
Я не могу понять, как это могло бы работать, поскольку Firebase в настоящее время поддерживает Node 6.11, который не поддерживает директивы импорта ES6?
Aodh
Если вы используете машинопись, проблема никогда не должна возникать. В последнее время я перенес большую часть своего кода в машинопись.
Заидфазил
2
zaidfazil, вы, вероятно, должны записать все предварительные условия в своем ответе. @ Да, это работает, если ты используешь Бабель так же, как обрисовал Константин в ответе. stackoverflow.com/questions/43486278/…
PostureOfLearning
1
Спасибо. это работало с машинописью и узлом 6 :)
Ахмад Мусса
4
Вместо того, чтобы импортировать и реэкспортировать с помощью операторов распространения, не могли бы вы просто иметь export * from './fooFunctions';и export * from './barFunctions';в index.ts?
whatsthatitspat
5

Этот формат позволяет вашей точке входа находить дополнительные файлы функций и автоматически экспортировать каждую функцию в каждый файл.

Сценарий главной точки входа

Находит все файлы .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 Searched For": query
    });
});

const searchTest = functions.https.onRequest((req, res) => {
    res.send({
        "searchTest": "Hi There!"
    });
});

module.exports = {
    query,
    searchTest
}

http доступные конечные точки имеют соответствующие имена

✔ functions: query: http://localhost:5001/PROJECT-NAME/us-central1/query
✔ functions: helloWorlds: http://localhost:5001/PROJECT-NAME/us-central1/helloWorlds
✔ functions: searchTest: http://localhost:5001/PROJECT-NAME/us-central1/searchTest

Один файл

Если у вас есть только несколько дополнительных файлов (например, только один), вы можете использовать:

const your_functions = require('./path_to_your_functions');

for (var i in your_functions) {
  exports[i] = your_functions[i];
}

Мэтью Райдоут
источник
Не будет ли это иметь перегрузку при загрузке для каждого экземпляра функции, который раскручивается?
Ayyappa
4

Так что у меня есть этот проект, который имеет фоновые функции и функции http. У меня также есть тесты для юнит-тестирования. CI / CD значительно облегчит вашу жизнь при развертывании облачных функций

Структура папок

|-- package.json
|-- cloudbuild.yaml
|-- functions
    |-- index.js
    |-- background
    |   |-- onCreate
    |       |-- index.js
            |-- create.js
    |
    |-- http
    |   |-- stripe
    |       |-- index.js
    |       |-- payment.js
    |-- utils
        |-- firebaseHelpers.js
    |-- test
        |-- ...
    |-- package.json

Примечание: utils/ папка предназначена для обмена кодом между функциями

Функции / index.js

Здесь вы можете просто импортировать все нужные вам функции и объявить их. Не нужно иметь логику здесь. Это делает это чище по моему мнению.

require('module-alias/register');
const functions = require('firebase-functions');

const onCreate = require('@background/onCreate');
const onDelete = require('@background/onDelete');
const onUpdate = require('@background/onUpdate');

const tours  = require('@http/tours');
const stripe = require('@http/stripe');

const docPath = 'tours/{tourId}';

module.exports.onCreate = functions.firestore.document(docPath).onCreate(onCreate);
module.exports.onDelete = functions.firestore.document(docPath).onDelete(onDelete);
module.exports.onUpdate = functions.firestore.document(docPath).onUpdate(onUpdate);

module.exports.tours  = functions.https.onRequest(tours);
module.exports.stripe = functions.https.onRequest(stripe);

CI / CD-

Как насчет непрерывной интеграции и развертывания каждый раз, когда вы вносите свои изменения в репозиторий? Вы можете получить его с помощью Google Cloud Cloud сборки . Это бесплатно до определенного момента :) Проверьте эту ссылку .

./cloudbuild.yaml

steps:
  - name: "gcr.io/cloud-builders/npm"
    args: ["run", "install:functions"]
  - name: "gcr.io/cloud-builders/npm"
    args: ["test"]
  - name: "gcr.io/${PROJECT_ID}/firebase"
    args:
      [
        "deploy",
        "--only",
        "functions",
        "-P",
        "${PROJECT_ID}",
        "--token",
        "${_FIREBASE_TOKEN}"
      ]

substitutions:
    _FIREBASE_TOKEN: nothing
ajorquera
источник
я экспортировал, как вы сказали, но развертывание firebase обнаруживает тот, который находится в конце, например: согласно вашему коду он принимает только module.exports.stripe = functions.https.onRequest (stripe);
OK200
@ OK200 какую команду вы используете в командной строке firebase? Чтобы помочь вам, мне нужно посмотреть код
ajorquera
3

Существует довольно хороший способ организовать все ваши облачные функции на длительный срок. Я сделал это недавно, и это работает без нареканий.

Я организовал каждую облачную функцию в отдельных папках в зависимости от конечной точки запуска. Каждое имя облачной функции заканчивается на *.f.js. Например, если у вас onCreateи onUpdateтриггеры на user/{userId}/document/{documentId}затем создать два файла , onCreate.f.jsи onUpdate.f.jsв каталоге functions/user/document/и ваша функция будет называться 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);
      }
}

(1): Вы можете использовать любое имя, которое хотите. Для меня onCreate.f.js, onUpdate.f.js и т. Д. Кажутся более подходящими для того типа триггера, которым они являются.

krhitesh
источник
1
Такой подход действительно хорош. Мне было интересно, можно ли настроить, чтобы разрешить косые черты в именах функций, чтобы можно было разделять разные версии API, например (api v1, api v2 и т. Д.)
Алексей Сороколетов
Почему вы хотите сохранить разные версии облачной функции в одном проекте? Хотя вы можете сделать это, слегка изменив структуру каталогов, по умолчанию index.js развернет все облачные функции, если только вы не развернете выборочно или не будете использовать if-условия в вашем index.js, что в конечном итоге приведет к загромождению вашего кода
krhitesh
1
Я в порядке с развертыванием всего, я просто хочу, чтобы версии функций, которые я поставил (сработали http)
Алексей Сороколетов
Я ожидаю, что каждый триггер http находится в своем собственном *.f.jsфайле. Наименьшее, что вы можете сделать, - это переименовать файл для каждой версии, добавив суффикс, чтобы сделать его похожим на *.v1.f.jsи *.v2.f.jsт. Д. (При условии, что все ваши версии всех ваших http-триггеров работают). Пожалуйста, дайте мне знать, если у вас есть лучшее решение.
Критеш
1

Я использую загрузчик vanilla JS для автоматического включения всех функций, которые я хочу использовать.

├── /functions
   ├── /test/
      ├── testA.js
      └── testB.js
   ├── index.js
   └── package.json

index.js (загрузчик)

/**
 * The bootloader reads all directories (single level, NOT recursively)
 * to include all known functions.
 */
const functions = require('firebase-functions');
const fs = require('fs')
const path = require('path')

fs.readdirSync(process.cwd()).forEach(location => {
  if (!location.startsWith('.')) {
    location = path.resolve(location)

    if (fs.statSync(location).isDirectory() && path.dirname(location).toLowerCase() !== 'node_modules') {
      fs.readdirSync(location).forEach(filepath => {
        filepath = path.join(location, filepath)

        if (fs.statSync(filepath).isFile() && path.extname(filepath).toLowerCase() === '.js') {
          Object.assign(exports, require(filepath))
        }
      })
    }
  }
})

В этом примере файл index.js автоматически включает только каталоги в корневом каталоге. Это может быть расширено, чтобы ходить каталоги, честь .gitignore и т. Д. Это было достаточно для меня, хотя.

При наличии индексного файла добавление новых функций тривиально.

/test/testA.js

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

exports.helloWorld = functions.https.onRequest((request, response) => {
 response.send("Hello from Firebase!");
});

/test/testB.js

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

exports.helloWorld2 = functions.https.onRequest((request, response) => {
 response.send("Hello again, from Firebase!");
});

npm run serve выходы:

λ ~/Workspace/Ventures/Author.io/Firebase/functions/ npm run serve

> functions@ serve /Users/cbutler/Workspace/Ventures/Author.io/Firebase/functions
> firebase serve --only functions


=== Serving from '/Users/cbutler/Workspace/Ventures/Author.io/Firebase'...

i  functions: Preparing to emulate functions.
Warning: You're using Node.js v9.3.0 but Google Cloud Functions only supports v6.11.5.
✔  functions: helloWorld: http://localhost:5000/authorio-ecorventures/us-central1/helloWorld
✔  functions: helloWorld2: http://localhost:5000/authorio-ecorventures/us-central1/helloWorld2

Этот рабочий процесс в значительной степени просто «напиши и запусти», без необходимости изменять файл index.js каждый раз, когда новая функция / файл добавляется / модифицируется / удаляется.

Corey
источник
это не будет иметь при холодном старте?
Ayyappa
1

Вот простой ответ, если вы создаете облачные функции с машинописью.

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

Почти все ваши регулярные импорта в верхней части просто экспортируйте все функции из foo.ts.

export * from './foo';

Markymark
источник