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 index = require('./routes/index.js');
    
      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
    


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


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

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

    Удачных выходных…
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 20
    • 0
      А ещё есть Sencha Desktop Packager. Платная, зато не нужно городить огород с NodeJS, сетью и т.п. Для кроссплатформенной разработки вполне годится, имхо.
      • +2
        Статья на эту тему была бы уместна…
        • +6
          есть и просто node-webkit, без express, без сети, кросплатформенный и бесплатный
          • 0
            Сыроват этот Sencha Desktop Packager еще. Когда я последний раз его пробовал остановился на том, что у него нету поддержки history и наше веб приложение дальше первой страницы не куда не двигалось… Хотя может сейчас уже исправили, обещали добавить в скором времени. Плюс все запросы работали только через jsonp потому что policy не позволяла делать кроссайт запросы. Хотя в phonegap нашли решение этой проблемы.
            • +1
              Есть еще www.tidesdk.org/ — бесплатный. С его помощью заворачивал одну «софтину» на extjs
            • –8
              Как? Тут до сих пор нет картинки про буханку хлеба и троллейбус?
              • 0
                Да ладно, оригинальная же идея — засунуть сервер и клиент в одно и то же приложение.

                Сперва выглядит дико, я допускаю это; но затем ответ на вопрос «но зачем?» становится очевиден: затем, чтобы не переписывать сервер с нуля в форме так называемого «одностраничного» веб-приложения, а пользоваться этим сервером в готовом виде. (Ну если сервер готов уж совершенно — так что целая куча совершённого ранее труда не должна просто так уйти, как говорится, коту под хвост.)

                Вот для разработки GUI-приложений «с нуля» я такой подход не рекомендовал бы.
              • –1
                И что вас смущает? Поделитесь своими проблемами с авторами www.mapbox.com/tilemill/ или www.greenheartgames.com/app/game-dev-tycoon/
              • +1
                Вызывает вопрос поддержка технологий вебкитом, встроенным в node-webkit.js. Судя по всему, node-webkit использует какой-то свой форк вебкита, в связи с чем какие-то новшества могут отсутствовать. К примеру, сделать 3D игрушку на WebGL и затем распространять просто так законно не получится.
                • +2
                  Каждый раз поднимается этот вопрос, но ведь уже давно понятно, что подобные хаки что с node-webkit, что с phonegap / appcelerator, sencha desktop, qtwebkit не подходят для тех вещей, где нужна производительность. Написать игрушку на webgl — круто, да, но только для себя самого. Такие «обёртки» подходят для «формочных офисных приложений». Когда нужно быстро, дёшево накидать — и чтоб работало.
                  • 0
                    appcelerator явно лишний в этом ряду. У него конечно производительность тоже страдает, но он все таки не является оберткой-браузером
                    • 0
                      Да дело не столько в производительности, её, кстати, достаточно: тот же pixi.js показывает весьма впечатляющий результат. Заманчива именно перспектива писать приложение, которое как в браузере можно запускать, так и на десктопе.
                  • 0
                    А запустить вторую копию приложения? Или второе приложение, выполненное с использованием этого подхода?
                    • 0
                      Как вариант:
                      Номер порта который прослушивает «серверная» часть необходимо сгенерировать динамически. Функцию startServer выполнить не в виде immediate-function, а обычной функцией с параметром (номер порта) и вызывать её из webkit`а. Если приложение работает в классическом варианте предусмотреть передачу номера порта через параметры командной строки.
                      • 0
                        Да, с этим можно жить, но вариант не оч крутой. То есть можно забиндиться на порт, который потом захочет занять другое приложение, на чей порт мы случайно попали при генерации.
                        • 0
                          Возможно, отвечать на эту реплику через год с лишним — достаточно поздно; но я всё же отвечу (в интересах будущих читателей), что свободный порт можно сгенерировать вон тем модулем.
                    • 0
                      При таком подходе теряется возможность использовать скоуп node-webkit. Получается, что вы просто показываете сайт в милом окошке, все плюшки node-webkit придется забыть.
                      • 0
                        Согласен, это довольно логичный вывод.
                        • 0
                          Прошу прощения, написал не подумав: в манифесте node-webkit можно использовать ключ node-remote (более подробно тут), в котором указывается маска адресов / сайтов, которые могут использовать node-webkit скоуп (тема на github по этому поводу).

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.