Pull to refresh

Апгрейд организации (Google)Firebase Cloud Functions

Google Cloud Platform *
Awaiting invitation

Предыстория


Однажды столкнулся с, казалось бы, небольшой проблемой — организация облачных функций Firebase. Уверен многие столкнулись с тем, что при создании некоего приложения мы обязаны создавать каждую функцию отдельно, а это фактически клонирование модулей Node.Js, особенно критично это в условиях большого приложения. Уверен, многим первой пришла мысль, создавать функции в отдельных файлах/каталогах и require`ить их в index.js.


Отличная идея… для медленного сервиса


Дело в том, что таким образом:


// index.js
exports.function1 = require('./function1.js');
exports.function2 = require('./function2.js');
exports.function3 = require('./function3.js');
etc.

Firebase при запуске одной функции будет инициализировать все что находится в index.js включая все зависимости внутри, а все это, естественно, занимает время. Согласитесь, в 2018 году никто не будет ждать загрузку страницы более 5 секунд. А учитывая так называемый "Cold start", инициализация будет проходить достаточно часто, что тоже неприемлемо.


Решение проблемы


Поискав немного информацию по этому вопросу вы наткнетесь на вот такой комментарий в GitHub:



И поверьте, на сегодняшний день этот простой цикл — лучшее решение данной проблемы.


С помощью его и индексовый файл будет чист, и будет единое соглашение об имени файла (camelCase в данном случае), а это особенно полезно при работе в команде. Так же Firebase будет инициализировать только нужную функцию перед её исполнением.


Но есть ещё одна проблема: Google Cloud Platform (GCP) осуществляет запуск кода только в среде Node.Js v6, что лишает нас async/await и подобных, а все таки Node.js v8 уже имеет статус LTS.


Моё решение состоит в использовании транскомпилятора Babel, но код вовсе не обязательно транскомпилировать перед деплоем! Оказалось, что GCP поддерживает транскомпиляцию "на лету". То есть, используя опыт зарубежных коллег, мы чуть изменим этот цикл:


//index.js
const glob = require("glob");
const camelCase = require("camelcase");

// Настройка babel
require("babel-register")({
  ignore: './node_modules',
  extensions: [ ".js"],
  cache: true,
});

const files = glob.sync('./**/*.f.js', { cwd: __dirname, ignore: './node_modules/**' });

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

Вывод


Таким образом мы имеет удобную организацию кода с соглашением об именах и поддержкой функциональных особенностей Node.Js v8 и выше.


Удачи в познаниях.

Tags:
Hubs:
You can’t comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.