Чем же он меня привлек, и чем он отличается от известных Derby.js, Meteor.js, Sails.js, и др.?
А понравился он мне прежде всего тем, что не накладывает на разработчика совсем уж жестких ограничений (прежде всего на источники данных, на менеджеры пакетов, …), и при этом вносит некоторую структурированность в код, предлагая следовать MVC-модели. Не хочу здесь подробно останавливаться на всех его плюшках и особенностях, благо все отлично расписано на сайте проекта, а сразу перейду к «своим баранам».
Итак, задача залить Kraken.js-приложение на сервис Heroku, заставить его там работать, и, на сладкое, прикрутить Sockjs.
Оговорюсь, что все описанные далее действия я выполнял на Ubuntu 13.10, но думаю, что для других ОС сильных отличий быть не должно. Для начала идем на heroku.com, регистрируемся и скачиваем Heroku Toolbelt — консольный клиент для работы с Heroku. Вводим в коммандной строке:
$ heroku login
Теперь мы готовы к разворачиванию приложений на Heroku. Следующим шагом установим Kraken.js, для этого выполняем:
$ sudo npm install -g generator-kraken
Затем преходим в каталог с проектами и набираем комманду $ yo kraken и в интерактивном режиме отвечаем на вопросы генератора:
,'""`. / _ _ \ |(@)(@)| Release the Kraken! ) __ ( /,'))((`.\ (( (( )) )) `\ `)(' /' [?] Application name: Kraken-Sockets [?] Description: A test kraken application with socks.js [?] Author: <Ваше имя> [?] Use RequireJS? (Y/n) n
Генератор создал каталог одноименный приложению и базовую структуру Kraken.js-приложения. Рассмотрим структуру подробнее:
/config Тут лежат конфигурационные файлы приложения в формате json /controllers Тут весь роутинг и логика /lib Сюда можно положить свои и сторонние библиотеки /locales Файлы локализации /models Модели /public Web-ресурсы, статика /public/templates Тут лежат шаблоны /tests Функциональные и юнит-тесты index.js Точка входа в приложение (загрузчик)
Наберем команду npm start и по адресу localhost:8000 можем полюбоваться работающим Kraken.js-приложением. Хорошо, теперь пришло время залить его на Heroku. Но для начала нужно привести приложение в соответствие с требованиями. Файл package.json у нас уже есть, теперь нам нужно создать файл Procfile с таким содержанием:
web: node index.js
Этот файл является инструкцией для Heroku, как запускать наше приложение. Кроме этих файлов Heroku требует, чтобы приложение слушало порт, указанный в переменной окружения PORT. Через json-конфиги мы этого сделать не сможем. Специально для этих случаев в Kraken.js предусмотрен механизм программного конфигурирования. Метод отвечающий за программную конфигурацию находится в файле index.js. Мы должны придать ему следующий вид:
app.configure = function configure(nconf, next) { // Async method run on startup. nconf.set('port', Number(process.env.PORT || 5000)); next(null); };
Ну а теперь создадим git-репозиорий проекта:
$ git init $ git add . $ git commit -m "init"
И выполним:
$ heroku create kraken-test-socksjs
Heroku создаст нам приложение, доступное по адресу kraken-test-socksjs.herokuapp.com и сразу подключит нам удаленный репозиторий, push в который устанавливает приложение на сервер.
Пробуем:
$ git push heroku master
Заходим на kraken-test-socksjs.herokuapp.com и убеждаемся, что все работает. Но не спешим радоваться; самый первый коммит (например добавим что-нибудь в шаблон главной страницы) ломает все приложение. Дальше у меня ушло много часов просмотра логов (комманда $ heroku logs) и гугления. А все оказалось очень просто. Heroku, почему-то, теряет некоторые зависимости второго уровня (зависимости зависимостей приложения — звучит кошмарно, приведу пример: в нашем случае он теряет модуль formidable, от которого зависит модуль kraken-js). И еще он не выполняет grunt-таски по подготовке ресурсов (компиляция less, шаблонов, и т.д.).
Чтобы устранить эти проблеммы делаем следующее: в файле package.json переносим все devDependencies в dependencies и добавляем в dependencies модуль "grunt-cli": "~0.1.13". Это позволит нам вызывать grunt вручную при деплое приложения. После всех изменений файл package.json должен принять такой вид:
{ "name": "kraken-sockets", "version": "0.1.0", "description": "", "author": "Your Name", "main": "index.js", "scripts": { "test": "grunt test", "start": "node index.js", "postinstall": "./node_modules/grunt-cli/bin/grunt build --force" }, "engines": { "node": ">=0.10.0" }, "dependencies": { "kraken-js": "~0.7.0", "express": "~3.4.4", "adaro": "~0.1.x", "nconf": "~0.6.8", "less": "~1.6.1", "dustjs-linkedin": "~2.0.3", "dustjs-helpers": "~1.1.1", "makara": "~0.3.0", "mocha": "~1.17.0", "supertest": "~0.8.2", "grunt": "~0.4.1", "grunt-cli": "~0.1.13", "grunt-contrib-less": "~0.9.0", "grunt-dustjs": "~1.2.0", "grunt-contrib-clean": "~0.5.0", "grunt-contrib-jshint": "~0.6.4", "grunt-mocha-cli": "~1.5.0", "grunt-copy-to": "0.0.10" }, "devDependencies": { } }
Обратите внимание на скрипт "postinstall", который как раз готовит ресурсы приложения. С проблеммой ресурсов справились, а что делать с пропавшими модулями? Это видимо баг новой системы кэширования модулей Heroku. Напишу им тикет на днях, а пока я справляюсь с помощью плагина heroku-repo. Просто перед каждым «пушем» релиза я чищу кэш модулей коммандой:
$ heroku repo:purge_cache -a kraken-test-socksjs
Ух, с дружбой Heroku и Kraken.js справились, теперь самое приятное: прикрутим к Кракену Sockjs.
Sockjs распространяется в виде npm-модуля и отлично прикручивается к express-приложению, но для того, чтобы ее прикрутить нужен доступ к серверу (тот, что представлен модулем http, на который вешается express.js). Так вот в Kraken.js он хорошо спрятан от разработчика. Но, покопавшись в исходниках Кракена, я нашел как его выцепить. Приведу сразу готовый код, который должен быть вставлен в index.js на место этого участка:
kraken.create(app).listen(function (err) { if (err) { console.error(err.stack); } });
Вот он:
var k = kraken.create(app); k.listen(function (err) { if (err) { console.error(err.stack); } else { var http = k.app.get('kraken:server'); var sockjs_opts = {sockjs_url: 'http://cdn.sockjs.org/sockjs-0.3.min.js'}; var sockjs_echo = sockjs.createServer(sockjs_opts); sockjs_echo.on('connection', function(conn) { hub.sockjs_pool.push(conn); conn.on('data', function(message) { hub.sockjs_pool.forEach(function(con) { con.write(message); }); }); }); sockjs_echo.installHandlers(http, {prefix:'/echo'}); } });
На этом я закругляюсь. Весь код проекта можно посмотреть на github. Поиграть с развернутым приложением тут.
Очень надеюсь, что эта статься поможет кому-нибудь сэкономить время при отладке Kraken.js-приложений на Heroku и прикручивании к ним всяких вкусностей.
P.S. Это моя первая статья, поэтому конструктивная критика очень приветствуется.
ссылка на оригинал статьи http://habrahabr.ru/post/213199/
Добавить комментарий