Сегодня только ленивый не делает проект в сфере онлайн тревела. Это в принципе логично, тк рынок быстро растет, хотя свободных ниш мало, а бизнес сложный. Многие уже смогли поднять серьезные инвестиции на сервисы бронирования гостиниц или продажи путевок онлайн.
В декабре прошлого года мы вышли на этот рынок с проектом iknow.travel, сделав ставку на объединение продажи авиабилетов и контентного ресурса, но уже через 3 месяца (в феврале) решили переписывать проект по сути с нуля, причем билетную часть мы даже не вывели из теста на тот момент.
О том зачем это было сделано с точки зрения стратегии развития проекта мы выложим отдельный пост в ближайшее время. Сейчас же хотим описать какие задачи нам пришлось решать и какие технологии были использованы на пути от начального релиза авиабилеты+контент до конструктора путешествий (разработка новой версии заняла 3 месяца).
ЧТО БЫЛО
ЧТО СТАЛО
ЧТО ДЕЛАЛИ
Изначально мы поставила перед собой цель: оставить сайт полностью открытым поисковикам, при этом сделать в стиле одностраничного приложения. У одностраничных сайтов есть сложность с SEO. Google в таких случаях рекомендует так называемые Hash Fragments. Суть вкратце такова: все ссылки начинаются с "#!", а робот лишь заменяет "#!" на "?_escaped_fragment=", делает запрос и ждёт в ответ статичный HTML. И всё работает. Мы предпочли старый добрый метод. Большая часть сайта доступна в HTML, что дает поисковикам увидеть страницы как на обычном статичном сайте (хотя без компромиссов не обошлось). Правда ходят слухи, что Googlebot уже понимает AJAX, но как-то мы им не склонны доверять. А с обычным браузером работаем по HTML5 PushState (поддержка которого есть во всех современных браузерах кроме IE 9), с автоматическим переходом на hash URL, если HTML5 PushState недоступен. А как бы сделали вы?
ДАЛЕЕ, ВЫБОР СТЕКА
У нас принято выбирать язык под задачу. Для серверного фронтенда оптимальным выбором стал node.js. Эта достаточно популярная платформа позволила нам разделить код и шаблоны между клиентом и сервером. JavaScript — хороший функциональный язык. Но чистый JS изматывает отсутствием синтаксического сахара и утомителен при поддержке, поэтому мы используем CoffeeScript.
BACKBONE
Наш клиент написан на базе Backbone. Backbone — JS-фреймворк для интерактивных приложений. Всё строится на базе 4 концепций:
- Model
- View
- Collection
- Router
Их толкование в Backbone отличается от общепринятых. Во-первых, модель отделена от базы. В комплекте идёт привязка к REST CRUD API, но есть адаптеры и к HTML5 LocalStorage, WebSockets. Во-вторых, View обычно вовсе даже не View, а контроллер в привычном понимании. Оговорюсь, что терминология — дело сугубо субъективное, и авторы Backbone прямо говорят: их заготовки открыты для любых подходов. Очень важно выбрать и придерживаться одного подхода. Что скажете?
Кстати для старта с Backbone рекомендуем посмотреть вот это (будем рады перевести для Хабра — пишите, если нужно).
MongoDB
Параллельно с выбором стека технологий, на которых будет построен клиент, перед нами стоял вопрос выбора СУБД для хранения данных.
Так как предметная область для нас была новой, было очевидно, что не стоит рассчитывать на то, что единожды спроектированная модель будет достаточно хорошей, чтобы ее не пришлось менять по мере разработки и развития проекта. В NoSQL мы рассчитывали получить более высокую скорость выполнения запросов, более удобное и простое хранение сложных данных, гибкость. Понимание того, что мы не раз поменяем схему базы, полностью обнулило шансы реляционных баз оказаться в стеке технологий нашего проекта.
По итогам анализа нескольких вариантов NoSQL СУБД, мы остановили свой выбор на MongoDB, из-за хорошего сочетания в ней широких возможностей с высокой скоростью работы. В частности, нас привлекли способности MongoDB по индексации массивов, удобные шардинг и репликация, хорошая документация. Также в пользу MongoDB говорит хорошая поддержка этой СУБД и её применение во многих успешных проектах (полный список тут, среди них такие гиганты как Disney, Craiglist, Foursquare).
Хотя мы изначально проектировали схему хранения данных с учетом особенностей документно-ориентированных СУБД, для уменьшения как времени выполнения запросов, так и размеров базы, нам пришлось неоднократно изменить схему базы. Например, мы столкнулись с необходимостью поддержки больших многомерных индексов для обеспечения быстрой фильтрации постов, но наша попытка оптимизировать схему хранения данных для обеспечения максимальной скорости выполнения запросов привела к экспоненциальному росту размера как индексов, так и самих данных, в результате чего мы поняли, что не сможем поддерживать такую базу из-за ее требований к оперативной памяти. В итоге мы нашли достаточно красивое решение, обеспечившее высокую скорость выполнения всех запросов без чрезмерного увеличения размеров индексов и данных. Однако, несмотря на то, что на данный момент достигнуты приемлемые показатели по скорости работы и потребелению ресурсов, мы понимаем, что с ростом проекта нам еще не раз придется модифицировать текущее решение.
РЕЗУЛЬТАТ
Если интересно посмотреть, что в итоге вышло и как работает, то для теста мы выложили обновленный проект вот сюда.
Для доступа к авиабилетам (если кому захочется туда залезть) на старом сайте используйте код: i3n7wt0a8el
Еесли правильно пост куда-то перекинуть, то скажите куда. За фидбек заранее спасибо. Нам во многом приходилось двигаться быстро (чтобы успеть к сезону отпусков) и интуитивно, т.к. подобную систему строили впервые. С радостью ответим на ваши вопросы.
Автор: Atreides07