HTML/CSS/JS + Node.js + node-webkit = Кроссархитектурные приложения

HTML/CSS/JS + Node.js + node-webkit = Кроссархитектурные приложения
С ростом популярности node.js он становится всё более привлекательным для разработки приложений. По крайней мере я в последнее время очень часто использую эту технологию для быстрой разработки оных. И на данный момент, технологически нет никаких препятствий для разработки кроссплатформенных приложений на одном языке. И не только классических Web-приложений (клиент-сервер) но и десктопных.

1. Если нужен быстрый старт, ставим express

npm install express

2. Создаём файл server.js примерно следующего содержания:

  var express = require('express');
  var http = require('http');

  var app = express();
  // Куча всяких настроек express`а        

  app.get('/', index.index);

  http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

3. Создаём файл index.js и кладём его в папку routes

exports.index = function(req, res){
  res.render('index', {});
};

4. Создаём index.ejs (я использую ejs как шаблонизатор) и кладём его в папку view

<!DOCTYPE html>
<html>
  <head>
      <meta charset="utf-8">
      <title>Hello world</title>
</head>
<body>
    <h1>Hello world!</>
</body>
</html>

Вуаля!

Запускаем

node server.js

Остаётся скопировать файлы на сервер, настроить nginx на проксирование запросов к нашему сервису… ну это Вы знаете. Но ведь не всегда есть желание или возможность возится с сервером. И даже если запускать проект локально… много возни. Хочется чего-нибудь «из коробки». Чтобы кликнул мышкой на ярлыке и приложение запустилось.

Проект node-webkit, анонсирование которого имеется на хабре, пригодится для сборки подобного.
Суть технологии в том, чтобы можно было внедрить api node.js в клиентский javascript-код. Т.е. вы можете соединятся с БД и файловой системой из клиентского кода напрямую, без посредников. Звучит заманчиво, и кстати работает, но мне не очень по душе такое смешение. Получается исключительно десктопное приложение. Мне по нраву другой вариант.
Приложение выполнено в классическом для web-приложений стиле: клиентский код и серверный. И я должен иметь возможность запускать его как на сервере, предоставляя многопользовательский доступ и как локальное (однопользовательское) приложение.

Вот рецепт:
1. node-webkit должен знать о стартовой html-странице которую он будет отображать первой.
дописываем в package.json следующее

"main": "nw-start.html"

2. nw-start.html будет следующего содержания

<!DOCTYPE html>
<html>
<head>
    <script>
        function bodyOnLoad(){
            require('./server.js');
            window.location.assign('http://localhost:3000/');
        }
    </script>
</head>
<body onload="bodyOnLoad()">
    <h1>
        Loading...
    </h1>	
</body>
</html>

3. Весь код server.js сделаем immediate-функцией.

(function startServer(){
    var express = require('express');
    var app = express();
    ....
    http.createServer(app).listen(app.get('port'), function(){
      console.log('Express server listening on port ' + app.get('port'));
    });
})();

4. Упаковываем весь проект в zip-архив nw-project.zip
5. Запускаем

nw nw-project.zip

cc6587495c967062eee7cdb6d136ff62
После недолгой паузы во время которой загружается «серверная» часть
00fb2eb21aa94c8786c290b9f164f82c

Суть происходящего достаточно проста. node-webkit загружает стартовую страницу. После этого выполняется клиентская функция bodyOnLoad. bodyOnLoad загружает модуль server.js (вызов node.js require). Вызов приводит к исполнению кода в server.js и, следственно, запуску http-сервера. Осталось только сменить URL страницы, что и делает window.location.assign(‘http://localhost:3000/’).

Подобный подход позволяет не меняя архитектуры web-приложения сделать его desktop-версию. Правда надо понимать, что за эту простоту придётся заплатить некоторой производительностью… ведь обмен данными будет происходить не напрямую, а через сетевые запросы.

Удачных выходных…