- PVSM.RU - https://www.pvsm.ru -

От парусов до кракена, или как я фреймворк выбирал

Доброго времени суток, уважаемые читатели Хабра. Всем давно известно, что во вселенной node.js существует привеликое множество фреймворков на любой вкус и цвет. Каждый из них удовлетворяет своим потребностям и содержит разнообразный набор возможностей и собственную архитектуру и иногда, чтобы сделать выбор, требуется взглянуть каждому из этих «зверей» под капот и провести аналитику. В моем случае требовался фреймворк уже более менее обладающий собственной архитектуройд; выбор происходил между 4 инструментами: kraken.js [1], sails.js [2], meteor.js [3] и derby.js [4]. Чтобы узнать о том, как это было, прошу под кат.

Derby.js vs. Meteor.js

Эти два фреймворка уже подвергались сравнению [5] и я решил объединить их в одну секцию. Перечислю лишь те качества, которые показались для меня решающими при отказе от данных фреймворков:

  • Оба позволяют выполнять JavaScript и рендерить шаблоны как на клиенте, так и на сервере, вопрос разве что в том, как определяется, что клиентское, а что серверное;
  • Интегрируются с MongoDB (или Redis в случае с Derby.js), что существенно снижает область их применения (если бы они были независимы от источников данных, возможно я бы и смирился с такой организацией кода в проекте);
  • Система менеджмента пакетов в случае с meteor.js;
  • Отсутствие документации в случае с derby.js (необходимо лезть в код, когда требуется понять «откуда ноги растут»);

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

Kraken.js

Kraken.js — это MVC фреймворк, выпущенный компанией PayPal относительно недавно, распространяемый как модуль npm, с основным акцентом на безопасности и поддержке интернационализации в приложении.

Состав

Помимо ядра в состав фреймворка входят еще четыре модуля:

  • Lusca [6] — отвечает за безопасность в приложении
  • Kappa [7] — реализует локальный proxy-сервер для npm-пакетов
  • Adaro [8] — надстройка над шаблонизатором dust.js [9] добавляющая различные вспомогательные средства
  • Makara [10] — добавляет поддержку интернационализации в шаблонах

Эти модули являются независмыми друг от друга (за исключением makara, который опирается на функционал adaro) и могут быть подключены и использованы в любом node.js приложении.

Структура приложения

Своей структурой приложение очень сильно напоминает структуру любого MVC-приложения, с хранением файлов по их функицональному назначению:

/config - конфигурационные файлы
/controllers - контроллеры
/locales - .property-файлы локализации
/lib - общие библиотеки используемые по всему приложению (не понятно зачем, ведь все это можно хранить в npm модулях)
/models - модели данных
/public - web-ресурсы доступные публично
/public/templates - клиентские и браузерные шаблоны
/tasks - разбитые по файлам grunt-задачи автоматически регистрируемые с применением плагина grunt-config-dir
/tests - юнит и функцональные тесты
index.js - главный файл приложения
Конфигурация

В то время когда в node.js есть CommonJS модули, с помощью которых мы можем реализовать динамическую конфигурацию приложения, kraken.js использует два .json-файла для development и production окружений, что существенно ограничивает наши возможности. Но, не смотря на данные ограничения, т.к. kraken.js базируется на уже набравшем популярность среди web-развработчиков фреймворке express.js [11], конфигурация его приложения может быть произведена любыми известными вами способами прямо в файле index.js или же с помощью самописного модуля конфигурирующего приложение. Кроме того, есть дополнительный модуль meddleware [12], существенно упрощающий конфигурацию middleware's [13] в вашем приложении.

Роутинг

Тут можно сказать, что он как бы есть, и в то же время его и нет. Весь роутинг выполняется вручную в файле контроллера, главной функции которого, предоставляется доступ к объекту router, и выглядит это следующим образом:

module.exports = function (router) {
    var model = new IndexModel();

    router.get('/', function (req, res) {
        res.render('index', model);
    });
};

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

Модели

Здесь создатели фреймворка решили предоставить разработчику полуную свободу выбора, дело в том, что модели в kraken.js являются обычными JavaScript-объектами со своими свойствами. Так что, выбираем любую понравившуюся вам ORM, устанавливаем ее через npm и вперед!

Шаблоны

Тут не к чему придраться. Шаблонизатор поддерживает фильтры, блоки-секций, условные конструкции, в общем обеспечивает разработчика всем необходимым инструментарием и даже позводяет компилировать шаблоны для использования их на клиенте.

Интернационализация

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

index.greeting=Hello {name}!
index.bye=Bye {name}!

Возможно в случае с простыми предложениями это еще хоть как-то сработает, но представьте, что будет в случае со сложными предложениями…

Sails.js

Sails.js был спроектирован и разработан Майком МакНилом [14] для создания масштабируемых приложений реального времени.

Состав

Sails.js состоит из ядра, которое построено из npm-модулей созданных и поддерживаемых другими разработичками, но и среди них имеется один очень интересный модуль — это ORM waterline [15], которая может выполнять миграции баз данных в полу-автоматическом режиме, и написанная специально для sails, и с легкостью подключаемая к любому node.js приложению. Кроме того, в ядро встроена поддержка генерации кода, которая может быть использована прямо из коммандной строки [16]. Кроме того имеется встроенная поддержка websocket's, позволяющая обрабатывать запрос поступивший через socket, как обычный запрос.

Структура приложения

Структура очень похожа на MVC приложение, с более детальным дроблением по функциональным возможностям.

api/
    controllers/ - контроллеры
    models/ - модели
    policies/ - политики управления доступом к методам контроллеров
    ...
    services/ - singleton-сервисы используемые по всему приложению
assets/ - файлы которые будут в дальнейшем помещены в public директорию сайта
config/ - файлы конфигурации
tasks/
    config/ - grunt-задачи
    register/ - регистраторы grunt-задач
    ...
views/ - шаблоны
Gruntfile.js - файл для регистрации и запуска grunt-задач из окна терминала
app.js - главный файл приложения
.sailsrc - главный файл конфигурации приложения

Подробнее о назначении каждого файла, можно узнать из документации [17], которая позволяет одним нажатием на директорию или файл узнать его назначении.

Конфигурация

Sails.js тоже основан на базе express.js, но в отличие от kraken.js он не предоставляет разработчику прямого доступа к объекту приложения и вся конфигурация выполняется посредством .js-файлов, которые представляют из себя CommonJS модули экспортирующие объекты отвечающие за настройку одного из компонентов ядра. Этот механизм позволяет отделить друг от друга настройку баз данных от найстройки HTTP-сервера, но очень сильно ограничивает возможности по конфигурации специфичных свойств приложения, например у меня вызвало сложность поменять путь по-умолчанию откуда будет происходить рендеринг шаблонов. Если же дело касается middleware, то вы можете его слегкостью подключить расположив его в секции middleware файла config/http.js.

Роутинг

Тут не к чему придраться. Роутинг настраивается путем указания нужного пути в файле config/routes.js в соответствующей секции и выглядит следующим образом:

module.exports = {
  'get /signup': { view: 'conversion/signup' },
  'post /signup': 'AuthController.processSignup',
  'get /login': { view: 'portal/login' },
  'post /login': 'AuthController.processLogin',
  '/logout': 'AuthController.logout',
  'get /me': 'UserController.profile'
}

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

Модели

Как уже было сказано выше, в состав sails.js входит очень мощная ORM, которая основана на использовании адаптеров в различным источникам данных, которые существуют для множества известных баз данных. Модель представляется в виде CommonJS модуля экспортирующего свойства модели, которыми в дальнейшем будет расширен базовый класс коллекции Waterline.Collection. В ORM встроена поддержка нескольких дополнительных типов полей, которые применяют специфические валидаторы на протяжении всего жизненного цикла модели (подробнее читайте в документации), а так же возможность указывать для каждой модели определенное соединение с базой данных, которое будет использовано при записи и чтении данных модели. Кроме всего этого, есть встроенная поддержка пагинации, сортировок и обработчиков событий.

Типичный пример файла модели:

module.exports = {
  connection: 'disk',

  attributes: {
    firstName: {
      type: 'string',
      required: true
    },

    lastName: {
      type: 'string',
      required: true,
    }
  }
});

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

Шаблоны

Sails.js имеет поддержку большинства известных шаблонизаторов за встраивания применения библиотеки consolidate.js [18] от автора фреймворка express.js, что несомненно упрощает применение шаблонов в приложении. Просто выбираешь, и используешь!

Интернационализация

Поддержка переводов присутствует в sails.js на протяжении всего жизненного цикла приложения, будь то серверный код, шаблон или .js-файл, ведь внутри sails.js использует библиотеку i18n [19]. Сами же переводы складываются в .json-файлы, и могут быть дополнены автоматически при попытке перевода текста, которого еще нет в файле. С одной стороны автоматическое наполнение создает проблемы по своевременному переводу, но всегда можно создать grunt-задачу, которая просканирует содержимое нужных файлов и соберет весь текст для переводов.

Так что же ты выбрал?

Подводя итог, я уме у меня сформировалась следующая таблица классификации, по пятибальной системе.

Конфгурация Роутинг Модели Шаблоны Интернационализация
Meteor.js 3 5 4 4 2
Derby.js - - - - -
Kraken.js 5 2 5 4 3
Sails.js 4 5 4 5 4

Не трудно догадаться, что мой выбор пал на sails.js, потому что мне более близка по духу структура проекта используемая фреймворком, и те возможности, которые он предоставляет «из коробки». Конечно же он имеет минусы касающиеся конфигурации и интернационализации, но это те минусы, с которыми в моем случае можно смириться или же реализовать, если мыслить согласно концепции фреймворка. Этой статьей, я ни в коем случае не склоняю вас в сторону того или иного инструмента, выбирайте сами, что вам близко по духу, и да прибудет с вами сила!

Автор: seth2810

Источник [20]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/69859

Ссылки в тексте:

[1] kraken.js: http://krakenjs.com/

[2] sails.js: http://sailsjs.org/

[3] meteor.js: https://www.meteor.com/

[4] derby.js: http://derbyjs.com/

[5] сравнению: http://habrahabr.ru/post/191664/

[6] Lusca: https://github.com/krakenjs/lusca

[7] Kappa: https://github.com/krakenjs/kappa

[8] Adaro: https://github.com/krakenjs/adaro

[9] dust.js: http://linkedin.github.io/dustjs/

[10] Makara: https://github.com/krakenjs/makara

[11] express.js: http://expressjs.com/

[12] meddleware: https://github.com/krakenjs/meddleware

[13] middleware's: http://expressjs.com/4x/api.html#middleware.api

[14] Майком МакНилом: http://michaelmcneil.com/

[15] waterline: https://github.com/balderdashy/waterline

[16] коммандной строки: http://sailsjs.org/#/documentation/reference/cli

[17] документации: http://sailsjs.org/#/documentation/anatomy/myApp

[18] consolidate.js: https://github.com/visionmedia/consolidate.js/

[19] i18n: https://github.com/mashpie/i18n-node

[20] Источник: http://habrahabr.ru/post/237287/