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

в 12:00, , рубрики: derby.js, express.js, javascript, kraken.js, Meteor.JS, node.js, sails.js, Программирование

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

Derby.js vs. Meteor.js

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

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

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

Kraken.js

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

Состав

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

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

Эти модули являются независмыми друг от друга (за исключением 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, конфигурация его приложения может быть произведена любыми известными вами способами прямо в файле index.js или же с помощью самописного модуля конфигурирующего приложение. Кроме того, есть дополнительный модуль meddleware, существенно упрощающий конфигурацию middleware's в вашем приложении.

Роутинг

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

Состав

Sails.js состоит из ядра, которое построено из npm-модулей созданных и поддерживаемых другими разработичками, но и среди них имеется один очень интересный модуль — это ORM waterline, которая может выполнять миграции баз данных в полу-автоматическом режиме, и написанная специально для sails, и с легкостью подключаемая к любому node.js приложению. Кроме того, в ядро встроена поддержка генерации кода, которая может быть использована прямо из коммандной строки. Кроме того имеется встроенная поддержка 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 - главный файл конфигурации приложения

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

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

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 от автора фреймворка express.js, что несомненно упрощает применение шаблонов в приложении. Просто выбираешь, и используешь!

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

Поддержка переводов присутствует в sails.js на протяжении всего жизненного цикла приложения, будь то серверный код, шаблон или .js-файл, ведь внутри sails.js использует библиотеку i18n. Сами же переводы складываются в .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

Источник

* - обязательные к заполнению поля