From sails to kraken, or how I chose the framework

Good day, dear readers of Habr. Everyone has long known that in the universe of node.js there is a great many frameworks for every taste and color. Each of them meets its needs and contains a diverse set of capabilities and its own architecture, and sometimes, to make a choice, it is required to look at each of these "animals" under the hood and conduct analytics. In my case, a framework was already required, more or less having its own architecture, the choice occurred between 4 tools: kraken.js , sails.js , meteor.js and derby.js . To find out how it was, I ask under cat.

Derby.js vs. Meteor.js

These two frameworks have already been compared and I decided to combine them into one section. I will list only those qualities that seemed decisive to me when abandoning these frameworks:
  • Both allow you to execute JavaScript and render templates both on the client and on the server, the only question is how to determine what is client and what is server;
  • Integrate with MongoDB (or Redis in the case of Derby.js), which significantly reduces the scope of their application (if they were independent of data sources, maybe I would come to terms with such organization of code in the project);
  • Package management system in the case of meteor.js;
  • Lack of documentation in the case of derby.js (you need to get into the code when you need to understand "where the legs grow from");

Perhaps I would use separate components, but in general the tools, no matter how much they praised and PR, seemed to me very specific and completely life-saving developers.


Kraken.js is a relatively recent MVC framework released by PayPal, distributed as an npm module, with the main focus on security and internationalization support in the application.


In addition to the kernel, the framework includes four more modules:
  • Lusca - responsible for application security
  • Kappa - implements a local proxy server for npm packages
  • Adaro is an add-on for the dust.js template engine that adds various auxiliary tools
  • Makara - Adds Internationalization Support in Templates

These modules are independent of each other (with the exception of makara, which relies on adaro functionality) and can be connected and used in any node.js application.

Application structure

By its structure, the application very much resembles the structure of any MVC application, with the storage of files according to their functional purpose:

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


While node.js has CommonJS modules with which we can implement the dynamic configuration of the application, kraken.js uses two .json files for development and production environments, which significantly limits our capabilities. But, despite these restrictions, because kraken.js is based on the express.js framework that has already gained popularity among web developers , the configuration of its application can be done by any methods you know directly in the index.js file or using the self-written module configuring the application. In addition, there is an additional meddleware module that greatly simplifies middleware's configuration in your application.


Here we can say that he is, as it were, and at the same time he is not. All routing is performed manually in the controller file, the main function of which is granted access to the router object, and it looks like this:

module.exports = function (router) {
    var model = new IndexModel();
    router.get('/', function (req, res) {
        res.render('index', model);

This of course provides more flexibility in the configuration, but you don’t think that the framework is primarily a tool that is designed to reduce the number of manual actions applied by the programmer (now I’m probably going to rotten tomatoes, but in general it is). When your application grows to an acceptable size, managing paths with such a routing will not be very pleasant either ...


Here the creators of the framework decided to give the developer full freedom of choice, the fact is that the models in kraken.js are ordinary JavaScript objects with their own properties. So, select any ORM you like, install it through npm and go!


There is nothing to complain about. The template engine supports filters, block sections, conditional structures, in general, provides the developer with all the necessary tools and even allows compiling templates for use on the client.


Translation support is present only in templates, which significantly limits our capabilities on the server, because we can’t just take and transfer a dynamically assembled translation string in a template variable. In addition, the module that performs the translation itself relies on the use of .property files, the organization of which does not inspire much confidence:

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

Perhaps in the case of simple sentences this will somehow work, but imagine what will happen in the case of complex sentences ...


Sails.js was designed and developed by Mike McNeill to create scalable real-time applications.


Sails.js consists of a kernel that is built from npm modules created and supported by other developers, but there is one very interesting module among them - ORM waterline , which can perform database migrations in semi-automatic mode, and written specifically for sails , and easily connected to any node.js application. In addition, support for generating code is built into the kernel, which can be used directly from the command line . In addition, there is built-in support for websocket's, which allows us to process a request received through socket as a normal request.

Application structure

The structure is very similar to an MVC application, with a more detailed fragmentation of functionality.

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

More information about the purpose of each file can be found in the documentation , which allows one-click on a directory or file to find out its purpose.


Sails.js is also based on express.js, but unlike kraken.js it does not provide the developer with direct access to the application object and the entire configuration is done through .js files, which are CommonJS modules that export objects that are responsible for setting up one of core components. This mechanism allows you to separate the database configuration from the HTTP server setup, but it greatly limits the ability to configure specific properties of the application, for example, it made it difficult for me to change the default path from where the templates will be rendered. If it comes to middleware, then you can connect it with ease by placing it in the middleware section of the config / http.js file.


There is nothing to complain about. Routing is configured by specifying the desired path in the config / routes.js file in the corresponding section and looks like this:

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'

This mechanism is very convenient and allows you to configure the settings without specifying the HTTP method, display the template without using the controller, specify the data that will be transferred to the template, access policies that must be checked before giving the user access to a specific controller method.


As mentioned above, sails.js includes a very powerful ORM, which is based on the use of adapters in various data sources that exist for many well-known databases. The model is represented as a CommonJS module exporting model properties, which will further expand the base class of the Waterline.Collection collection. ORM has built-in support for several additional types of fields that are used by specific validators throughout the model life cycle (read the documentation for more details), as well as the ability to specify for each model a specific database connection that will be used when writing and reading model data. In addition to all this, there is built-in support for pagination, sorting and event handlers.

A typical example of a model file:

module.exports = {
  connection: 'disk',
  attributes: {
    firstName: {
      type: 'string',
      required: true
    lastName: {
      type: 'string',
      required: true,

When changes occur in the model structure, ORM automatically determines them at startup and if automatic conflict resolution cannot be made, it conducts a dialogue with the developer.


Sails.js has the support of most well-known template engines for embedding applications of the consolidate.js library from the author of the express.js framework, which undoubtedly simplifies the use of templates in the application. Just choose and use!


Translation support is present in sails.js throughout the entire application life cycle, whether it be server code, a template or a .js file, because inside sails.js it uses the i18n library . The translations themselves are added to .json files, and can be supplemented automatically when trying to translate text that is not already in the file. On the one hand, automatic filling creates problems for timely translation, but you can always create a grunt-task that scans the contents of the necessary files and collects all the text for translations.

So what did you choose?

To summarize, the following classification table was formed in the mind, according to a five-point system.


It is not difficult to guess that my choice fell on sails.js, because the project structure used by the framework and the opportunities that it provides “out of the box” are more similar to my spirit. Of course, it has drawbacks regarding configuration and internationalization, but these are the drawbacks that in my case can be reconciled or implemented, if you think according to the concept of the framework. By this article, in no case do I incline you towards this or that instrument, choose for yourself what is close to you in spirit, and may the force come with you!

Also popular now: