Приложение VK Offline: история создания и переход в Open Source

В рамках акции для разработчиков представляем статью от автора приложения VK Offline. 

Приложение VK Offline появилось в Chrome Web Store в августе 2011 года и за прошедшие полтора года превратилось из прототипа, представленного на Chrome-хакатоне в Питере, в полноценное (и теперь уже legacy) приложение для Google Chrome. Сегодня я выпускаю VK Offline 4.7 и отдаю его в сообщество разработчиков на github как opensource продукт.

Я хочу воспользоваться рупором Хром.РФ и в последний раз в качестве главного разработчика рассказать о том, что было, и о том, что будет с приложением. Половина этого поста будет о полезном опыте, который пригодится любому разработчику расширений/приложений, а другая половина о технической части для тех, кому интересно будет развивать само приложение. Скучно не будет.

Этапы разработки VK Offline

Начиналось все в конце лета 2011. Я активно изучал javascript и написание расширений/приложений для Google Chrome показалось мне крайне интересным. Хакатон, организованный питерской командой GTUG пришелся как нельзя кстати, а приглашенный эксперт Mike West из Google только укрепил веру в свои возможности. Две недели после хакатона я активно пилил приложение, попутно обсуждая главные его части с друзьями.

[offtopic] Оглядываясь назад, я считаю, что этот выбор был определяюще верным. Выбирая разработку расширений/приложений для Chrome, вы получаете потрясающее и классное API, самые современные веб-технологии, а также тот самый javascript-экспириенс, который трудно получить при разработке сайтов. Не бойтесь трудностей, которые возникнут у вас на этом пути. [/offtopic]

VK Offline 1.0

Реклама - наше все, и именно тогда мы с друзьями решили попробовать поснимать несколько простых промок к приложению, некоторые из которых вы видели на Хабре и Хром.РФ. Я не очень доволен получившимся результатом, но следующие смонтированные нами скринкасты были гораздо лучше, поэтому я думаю, что не все так страшно. Плюс изначально я взял такую тему, которую было достатчно трудно донести до людей.

После хакатона и конкурса я встроил функционал Google Voice Search в приложение. Мне до сих пор кажется, что это одно из самых интересных мест в приложении, хотя с точки зрения кода работает он не совсем тривиально. Затем я уже долго допиливал производительность приложения, ускорял скорость первой синхронизации, оптимизируя код внесения писем в WebDatabase.

Революцией стал выпуск 4 версии приложения, в которой полностью поменялась структура БД и пришлось писать сложную систему миграции пользователей 3 версии приложения на 4. Отлаживать это было очень тяжело, и при обновлении приложения все равно обнаружилось, что я не учел какие-то моменты, что сказалось на количестве пользователей приложения (сократилось с 30К до 22К). Главным же в 4 версии стало то, что изменился интерфейс, и по сути приложение получило свой нынешний вид с папками, real-time диалогами, вложениями с поддержкой drag-n-drop и др. Дальнейшая работа была уже над вылизыванием мелочей и исправлением утечек памяти.

Синхронизация в VK Offline

VK Offline v4

В версии 4.7 стали показываться аватарки друзей, которые исчезли после переезда статики ВКонтакте на другой домен. Также была исправлена ошибка с частым показом окон напоминания о ДР, и по просьбам стали поддерживаться emoji-картинки. Внутри же был произведен переход на шаблонизатор Hogan.js, а прототипы DOM-объектов перестали активно загрязняться, что должно улучшить производительность приложения.

Что было важно

Метрики. Когда все начиналось, была мысль только о том, что нужно фигачить код. Я рассматривал количество пользователей в Chrome Web Store как главную метрику и был доволен. Но когда приложение стало обрастать функционалом, стало интересно знать, пользуются ли люди им или нет. Так в приложении появились кастомные ивенты от Google Analytics и Яндекс.Метрики, о которых я рассказывал на DevFest. И именно по ним я стал ориентироваться при дальнейшем внедрении и изменении функциональности приложения. Для интереса: в день генерируется порядка 5М событий, по которым можно судить о работе приложения.

Статистика VK Offline

LocalStorage. Код приложения рос и приходилось запоминать данные, хранимые в key-value LocalStorage, для чего пришлось заводить отдельную страницу. Иначе данные в LocalStorage были бы сплошной помойкой, в которой было бы сложно ориентироваться при разработке.

Расширение функционала. Пока приложение росло, увеличивалась и изменялась структура БД. Приходилось не забывать про текущих пользователей приложения и к каждой версии писать свои скрипты миграции. На это тратилось время, но зато при обновлении текущая база пользователей страдала по минимуму и получала работающее приложение с новым функционалом.

Расширение базы пользователей. Набор базы пользователей в Chrome Web Store - достаточно трудное и непредсказуемое дело. Поэтому решение внедрить в приложение иконку лайка, клик по которой ставит лайк и репост этой записи, после чего ее видят все друзья пользователя, стало одним из определяющих. Именно это решение позволило приложению постоянно набирать базу пользователей все это время.

Обратная связь. Для обратной связи в 4 версии приложения я сделал отдельную форму, которая при отправке спрашивала разрешения пользователя к chrome.management.* API. Это позволило вместе с логом ошибок отправлять список установленных расширений. Несмотря на ограничения песочницы, за ее пределами часто возникали проблемы доступа к OAuth-авторизации.

Запрос прав в VK Offline

Все это время я старался отвечать на отзывы и вопросы пользователей, даже если они были неадекватными. Была создана группа ВКонтакте, я старался мониторить отзывы на Chrome Web Store, несмотря на то, что отвечать на них нельзя. Вобще это достаточно грустная тема, которая больше подходит для флейма. Главным выводом для меня наверное оказалось то, что полезного фидбэка в отзывах почти нет, а юные пользователи ВКонтакте зачастую обладают чересчур завышенными требованиями.

DevFest. Кстати в ноябре на DevFest 2012 я рассказывал о многих вещах, с которыми столкнулся при разработке. Я очень советую вам потратить 20 минут времени, и не повторять ошибки, которые вы повторите, если не потратите 20 минут времени... Ну вы поняли :)

Уже в процессе разработки концепция приложения переросла в "E-mail клиент и адресная книга на основе ваших данных ВКонтакте". Но на момент начала это был скорее бэкап ваших данных в приложении для Chrome. В нем не было поддержки real-time диалогов, вложений, да и многие другие вещи были написаны почти на коленке. Сейчас все стало сравнительно неплохо, хотя мне все равно стыдно за многие части кода. Но перфекционизм не всегда лучший союзник. И кстати о коде.

Техническая часть VK Offline

i18n

Локализации в приложении изначально не было и пришлось достаточно много повозиться, вставляя ее в код. В процессе допиливания я пришел к решению, когда вся локализация хранится в одном файле i18n/locales.json, а затем при сборке разносится по файлам локалей _locales/%locale%/messages.json. Сборка локалей осуществляется командой grunt i18n.

Шаблоны и шаблонизатор

Это достаточно смешно, но до версии 4.7 весь UI отрисовывался с помощью document.createElement()/element.appendChild() итд. Теперь VK Offline использует mustache-шаблоны и шаблонизатор hogan.js от Twitter. Сборка шаблонов осуществляется командой grunt templates. Шаблоны хранятся в папке templates.

DOM Traversing

Я изначально был противником встраивания jQuery в код проекта. Он достаточно большой, да и все проверки на браузер совсем не нужны. Поэтому для DOM Traversing я использую js/dom.js, который написан на основе библиотеки DOM5. Общая идея заключается в том, что в в прототип Element подмешивается кастомный объект, позволяющий манипулировать DOM-элементами более удобно и просто.

Grunt

Grunt используется для сборки локализаций, шаблонов и релизов (grunt release).

Background page (backend.js)

Это ядро приложения, его фоновая страница и постоянно работающий код. К нему обращаются табы приложения, и он рассылает им информацию о том, что что-то изменилось. Одни из самых важных объектов в нем: mailSync (синхронизация сообщений), friendsSync (синхронизация списка друзей) и longPollEventsRegistrar (real-time диалоги).

Работа с БД (databaseManager.js)

Огромная череда методов, которые экспортирует DatabaseManager. К каждому методу написан подробный jsDoc, так что при использовании проблем возникнуть не должно.

Миграция при обновлении (migrationManager.js)

Скрипты миграции находятся в массиве migrateData, который содержит названия версий и таски, которые необходимо выполнить при миграции с более низкой версии приложения на эту и выше. Таски выполняются поэтапно. Сам MigrationManager экспортирует только один метод - start, а в callback передает код результата окончания процесса миграции.

Запросы к API ВКонтакте (reqManager.js)

Все запросы к API делаются через ReqManager. Он следит за повисшей сетью, неудачными ответами и пр. Экспортируемые методы: apiMethod, forceUrlGet, abort и abortAll.

Настройки (settingsManager.js)

Настройки хранятся в LocalStorage, но для более простой работы с ними существует SettingsManager, который позволяет получить значение настройки через вызов SettingsManager[key] и записать новое значение настройки с проверкой с помощью SettingsManager[key] = value.

Работа со звуком (soundManager.js)

Звук может работать через Web Audio API, а если он недоступен, то через HTML5 Audio. SoundManager следит за доступными API и воспроизводит звук через доступный интерфейс. Единственный экспортируемый метод - play.

Работа с LocalStorage (storageManager.js)

Как известно, LocalStorage это топорный key-value, который при сохранении данных преобразует их в строки. Но поскольку разработка приложения начиналась тогда, когда chrome.storage еще не существовал, приходилось писать свою обертку над LocalStorage для более удобной работы. Экспортирует методы set, get и remove. Метод get помимо всего позволяет производить минапуляции над данными и получать их ровно в том виде, в котором предполагается их хранение.

Отрисовка (ui.js)

К сожалению, многие части ui.js остались со времен VK Offline 2/3, поэтому он достаточно объемный. Может быть стоило использовать backbone.js или что-то другое, а не городить свои велосипеды из full/partial views. С другой стороны такой подход позволяет достаточно гибко перерисовывать части интерфейса, не трогая другие.

Это еще не конец (не просолился сознания огурец)

Для пользователей все это означает, что дальнейшее развитие приложения VK Offline будет продолжаться силами сторонних разработчиков. Если вы javascript-программист и хотите продолжить развитие этого проекта, то список возможных улучшений и задач вы можете посмотреть здесь.

Чтобы быть до конца честным - я вижу развитие VK Offline в качестве не legacy packaged app, но для этого нужны или огромная куча времени, или прямое сотрудничество с ВКонтакте. К сожалению ни того, ни другого у меня нет. С другой стороны я помню о том, что знаниями нужно делиться, а не хвастаться, поэтому если кому-то пригодится мой опыт, будет круто. Это еще не конец :)

Автор: +Dmitry Sorin

P.S. Ссылка на приложение в Chrome Web Store.