Лучшая файловая архитектура приложения LoopbackJS.

Перейти к профилю akkonrad

акконрад

26 марта

LoopbackJS — отличный фреймворк для быстрого старта с API для небольшого приложения. В этом случае достаточно архитектуры по умолчанию, предложенной LoopbackJS. К сожалению, когда ваше приложение имеет некоторую продвинутую логику и множество различных моделей, настраиваемых сценариев загрузки, удаленных методов и тонны хуков, это становится грязным и утомительным для поддержки кода.

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

Поведение LoopbackJS по умолчанию.

Когда вы создаете ванильный проект loopback с loopback-кли вы получите что-то вроде этого:

// ...

app.start = function() {
  // ...
};

boot(app, __dirname, function(err) {
  if (err) throw err;

// start the server if `$ node server.js`
  if (require.main === module)
    app.start();
});

Итак, когда мы добавляем загрузочный скрипт сервер/загрузки/загрузки-lvl1.js он будет загружен при запуске сервера.

// server/boot/boot-lvl1.js

'use strict';

module.exports = function enableAuthentication(app) {
  console.log('boot: level 1');
};

Все идет нормально. Но давайте представим ситуацию, когда у вас есть несколько моделей и у каждой из них есть несколько загрузочных скриптов, поэтому загрузочный каталог будет расти с каждым новым скриптом. Его невозможно организовать в каталогах со стандартной конфигурацией loopback. Давайте поместим загрузочный скрипт во вложенный каталог в файле boot и проверим, будет ли он вызываться.

// server/boot/nested/boot-lvl2.js

'use strict';

module.exports = function enableAuthentication(app) {
  console.log('boot: level 2');
};

Теперь при запуске сервера мы не увидим второй console.log в выводе консоли.


вывод консоли сервера проекта LoopbackJS API

Решение.

Чтобы решить эту проблему, нам нужно сообщить загрузочному сценарию замыкания на себя, чтобы он загружал файлы из более чем одного каталога. Поэтому нам нужно обновить загрузочный скрипт, чтобы загружать все каталоги, которые мы хотим. Нам нужно предоставить массив каталогов, откуда будут загружаться скрипты при загрузке.

const options = {
  appRootDir: __dirname,
  bootDirs: [ // <--- all locations that we want to load
    './boot/nested',    
    './boot/another',
    './boot/yet-another-one',
  ],
};

boot(app, options, function(err) {
  // ...
});


вывод консоли сервера проекта LoopbackJS API

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

Лучшее решение.

Итак, у нас есть куча скриптов и модулей. Наше приложение растет, и количество загрузочных скриптов тоже увеличивается. Естественно, в какой-то момент мы захотим обеспечить еще лучшую организацию нашего кода, создав больше подкаталогов. Это может выглядеть так:


Немного более сложная структура папок в загрузочном каталоге проекта LoopbackJS API.

Мы могли бы вставить каждый каталог в конфиг вручную, но это не очень хорошее решение, потому что нам нужно помнить об этом каждый раз, когда мы создаем каталог. Это может быть в сервер.js файл, загрузив каждый файл js, который находится внутри каталога server/boot. Я предлагаю установить какой-нибудь модуль, который сделает это за нас, например. читать Теперь наш сервер.js файл выглядит так:

// load module
const readdirp = require('readdirp');

// prepare settings for the readdirp moduleconst settings = {
  root: './server/boot',
  entryType: 'directories',
};

// list of directories to populate
const directories = [];

readdirp(settings)
  .on('data', entry => {
    // add each directory to the directories array        
    directories.push(entry.fullPath);   
  })
  .on('end', () => {

    const options = {
      appRootDir: __dirname,
      bootDirs: directories, // load directories
    };

    boot(app, options, ...);
  });

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

Лучшее решение.

Хорошо, мы обеспечили некоторый порядок, но все еще неоптимально хранить все в сценарии загрузки: вещи, связанные с моделью, авторизацию, пользовательский функционал загрузки и т. д. Было бы удобнее разделить то, что относится к моделям на уровень выше и положить в каталог модулей. Затем, внутри каждого модуля, мы могли бы организовать его дальше. Например, мы могли бы создать подкаталог для каждого из:

  • конфигурация: статические/постоянные переменные, в которых хранятся значения, которые не нужно скрывать в переменных окружения,
  • удаленные методы: здесь хранятся все пользовательские удаленные методы,
  • удаленные крючки : здесь могут быть все удаленные хуки,
  • хуки коннектора базы данных : как расшифровывается — любые разъемы крючки,
  • оперативные крючки: до… и после… крючков,
  • промежуточное ПО : здесь должно быть любое промежуточное ПО для конкретного модуля; глобальная конфигурация в server/middlerware.json все еще нуждается в обновлении, чтобы разместить промежуточное ПО на надлежащем этапе,
  • модельные методы : любые пользовательские методы модели,
  • помощники : все, что не подходит под вышеизложенное и содержит логин,
  • валидаторы : определение проверки модели и пользовательские функции проверки.

Эта структура потенциально сэкономит ваше время, когда через некоторое время вам придется вернуться к коду.

Наша структура будет выглядеть так:

Ресурсы

Все вышеперечисленное можно скачать из репозитория:

Если у вас есть другое представление о структуре, вы можете внести свой вклад здесь, я бы хотел улучшить его.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *