Когда возникает идея создать что-нибудь полезное, обычно очень хочется сделать прототип (или версию 1.0) как можно скорее. Для кого-то, видеть быстрый результат — это хорошая мотивация, чтобы развивать идею дальше; для других — главное «начать», всем известная истина, что доделывать/переделывать готовое намного легче, чем писать с нуля. Итак, в процессе очередного чаепития и обсуждения финансовых рынков, у нас появилась идея создания легкого сервиса для обмена идей и новостей, а также определения текущей ситуации на фынансовых рынках (т.н. тренды) — ведь зная тренды, можно более эффективно торговать.
В требованиях были: веб сервис, мобильная версия (желательно app), легкая коллективная админ-часть, и простой интерфейс.
Как у нас получилось мега-быстро «слепить» одновременно и веб и мобильную версию приложения CxInvestor и пойдет речь в этой статье.
Разработка
Первый вопрос, который нужно было решить — на чем писать сервер.
Без-серверный Firebase
Мои знания php ушли далеко в 90-ые, а писать небольшой, легкий сервер на ASP.NET или Java не очень-то хотелось. Идея написать «без-серверное» веб-приложение звучало слишком уж хорошо, но покопавшись в интернете, было решено все-таки попробовать Firebase. На создание аккаунта, базы данных и реализации простого примера ушло всего 20 минут. Стоит отметить, что кроме «реалтайм» базы данных, Firebase также имеет встроенную систему юзеров, привилегий и разных логин-интеграций с Facebook и Twitter. Фактически, вся система управления пользователями, паролями и привилегиями давалась на шару.
Ну… не совсем на шару, если у вас приложение покрупнее — минимальный платный апгрейд стоит $50/месяц.
Итак, Firebase:
Плюсы:
- Очень быстрая настройка
- Простота использования
- Скорость работы
Минусы:
- Нереляционная/NoSql база данных прекрасно подходит только для более менее простых случаев
- Цена — хотя это скорее плюс, так как поддержка, содержание серверов и безопасность того стоят
Вот как выглядит магия в Firebase:
var fb = new Firebase("https://YOUR.firebaseio.com/");
fb.set({ name: "Alex Wolfe" });
Адаптивный Bootstrap и AngularJs
Для фронтенда выбор был достаточно очевиден — использовать Twitter Bootstrap, чтобы можно было удобно работать с сервисом на любом девайсе, а вот AngularJs пришел в голову не сразу. Основным аргументом в пользу AngularJs было то, что это полноценный фреймворк, тоесть не нужно учить связки двух, а то и трех основных javascript библиотек (например, RequireJs + KnockoutJs). А также, AngularJs имеет хорошую модульную структуру, отделение презентации от логики, и поддержка длинных путей.
В целом, AngularJs нас не подвел, все возникшие проблемы решались быстро с помощью google, а добавлять новый фунционал в приложение было легко и приятно.
Итак, AngularJs:
Плюсы:
- Понятная модульная структура
- Встроенная система зависимостей
- Все веб елементы подписуются на переменные-данные, так что когда Firebase присылает изменения, на фронтенде все отображается автоматически
Минусы:
- Небольшое количество проблем/багов, которые или уже пофикшены в новой версии или легко обходятся
- Вес библиотек все-таки немаленький, но в долгосрочной перспективе должно окупиться
Вот так мы задаем зависимость одних модулей от других:
var controllerId = 'calendar';
angular.module('app').controller(controllerId, ['$rootScope', 'common', 'datacontext', calendar]);
function calendar($rootScope, common, datacontext) {
Мобильный Phonegap
Теоретически, сложив предыдущие три елемента (Firebase, Bootstrap и AngularJs), имеем уже готовый сервис, работающий в мобильных веб браузерах. Запаковать все в Phonegap и сделать из веб сервиса мобильное приложение было логическим дополнением.
Смущало несколько вещей:
- Пропустят ли приложение в AppStore — начитавшись историй о том как Apple не любит Phonegap-обертки, и взвесив все за и против, все-таки решили попробовать. К слову, не смотря на простоту нашего приложения, и явно не-iOS дизайн юзер интерфейса, наша первая версия все-таки прошла ревью со второго раза (в первом пакете я включил иконки не всех требуемых размеров)
- Стабильность и наличие нужных фич
- Скорость работы
Как оказалось, некоторые вещи-таки не работают так как хотелось бы, а скорость первой версии нашего приложения все же оставляла желать лучшего (но об этом дальше).
Перепробовав несколько разных плагинов для одного и того же функционала и помучившись с alert('yoo') в javascript-е (кто знает — поймет), я все-таки отладил функциональность и запустил рабочую версию на своем айфоне. На будущее, хочу отметить, что основные проблемы все-таки возникали просто с примерами, которые идут вместе с плагинами. Скорее всего, разработчики плагинов не успевают (или ленятся) вовремя обновлять примеры, так что в итоге мелкие синтаксические ошибки или изменения в параметрах вызовов приводят к тому, что приходится тратить целые вечера с чаем, дебагером и alert-ом, чтобы заставить приложение работать.
Со скоростью проблем оказалось намного больше! После оборачивания в Phonegap наше приложение выглядело прямо скажем совсем не-интерактивным (а некоторые части и вовсе тормозили жутко). Чудесное изобретение AngularJs скобочки, типа {{myData}}, в мобильном приложением оказалось прямо-таки проклятием, так как выскакивало то тут то там на доли секунд, и создавалось впечатление полного фейла. В итоге, основную часть системы пришлось переписать так, чтобы кешировать как можно больше и апдейтить елементы как можно реже. Все css и angular анимации пришлось убрать полностью (о чем, я в принципе, почти не жалею). А все скобочки {{myData}} пришлось заменить на ng-bind=«myData».
Дальше, максимально повыкидовался ненужный javascript, неиспользуемые css, и наконец, был добавлен FastClick:
<script type="application/javascript">
window.addEventListener('load', function () {
FastClick.attach(document.body);
}, false);
</script>
Результат? Приложение таки стало более интерактивным, конечно, скорость явно отличается от нативных приложений (не в лучшую сторону), зато неоспоримый плюс — Phonegap позволяет делать приложения сразу на все мобильные платформы.
Итак, Phonegap:
Плюсы:
- Обертка работает на всех платформах (разрабатываешь веб версию, а мобильную получаешь в подарок)
- Использовать вместе с build.phonegap.com очень просто
- Большинство мобильных фунций доступны как javascript плагины
Минусы:
- Отладка требует много времени и сил
- Если скорость приложения является ключевым фактором, phonegap может просто не подойти
Установка и настройка
Регистрация домена,
Билд система
Идея слепить маленькую билд систему прийшла сразу, так как нужно было автоматизировать обфускацию исходников и поддерживать версионность. Как оказалось, на самом деле можно (и нужно) автоматизировать еще много других задач, перед тем как собственно стартовать копирование в ftp-клиенте (что тоже можно автоматизировать).
В качестве билд скриптинга был выбран PowerShell, в виду модульности, простоты использования и хорошей работы с параметрами коммандной строки.
В качестве javascript компилятора был выбран Closure Compiler, а css компилировали с помощью yuicompressor.
Write-Output "Compiling js files..."
java -jar compiler.jar --language_in ECMASCRIPT5 --angular_pass `
--js $BaseDirscriptsjquery-2.0.3.js `
--js $BaseDirscriptsangular.js `
...
Итак, веб сервис готов и добавлен в google индекс, но осталась одна проблема — google bot не умеет запускать javascript на страничках, поэтому любой url, ведущий к AngularJs представлению (например, www.mywebsite.com/#!/myView), не будет корректно загружен google bot-ом, так как требует запуска javascript. Это, пожалуй, один из самых неприятных моментов при использовании AngularJs, так как это автоматически усложняет SEO вашего веб сервиса и добавляет еще работы вам как разработчику.
На текущий момент, рекомендация гугла (и других поисковиков) — это поддержка так называемых html-snapshots, которые будут отображать запрашиваемую страничку без javascript и польностью (с этим строго — google наказывает если html-snapshot и javascript версия сильно отличаются).
Снепшот должен быть доступен по специальному url: www.mywebsite.com/?_escaped_fragment_=/myView
Выглядит жутковато… к счастью, на помощь пришли apache правила, которые можно определить в .htaccess файле:
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=/?(.+)$ [NC]
RewriteRule ^ /snapshots/%1.html? [NC,L]
А дальше просто — обходим все свои вьюшки и сохраняем готовые html файлы после того как javascript загрузил все данные и полностью отработал. В последствии PowerShell помог нам автоматизировать этот процесс и автоматически обновлять snapshots на сервере. Также, в интернете полно сервисов, которые сделают все за вас за скромную оплату (нужно только поставить похожий рул в .htaccess, чтобы перенаправить google bot на веб сайт сервиса-подписки).
А что дальше?
В процессе разработки, многие первоначальные фунциональные требования были изменены и добавилось много свежих идей.
Несомненно, следующий шаг — раскрутка нашего сервиса и мобильных приложений, но об этом в другой раз.
Автор: Vitko