Привет, я Ксавье, соучредитель компании Aircall. Наша замечательная команда из 40 человек (наполовину технологи, наполовину бизнес) создает лучшую телефонную систему для компаний.
Мы только что собрали 8 миллионов долларов и надеемся расширить наши офисы в Нью-Йорке и Париже. . Ознакомьтесь с нашими 20+ предложений!

В этом сообщении блога описываются технические решения, которые мы сделали для создания наших веб-приложений.

Заявление об ограничении ответственности: это не сообщение о том, что все приложения должны быть созданы как это. Создайте свою систему в соответствии с вашими техническими потребностями и используйте инструменты, которые будут удобны вашей команде. Пингуйте меня, если знаете, как сделать наш стек еще лучше :)

Еще в начале 2014 года

Когда мы начали создавать Aircall, мы пытались создать простую, гибкую и не требующую оборудования телефонную систему для небольших команд и малого и среднего бизнеса. Наша целевая учетная запись будет иметь до 10 товарищей по команде, около 5 номеров, ~ 200 импортированных контактов и будет совершать и принимать не более 100 звонков в день.
Не шучу, это даже было написано в наших Условиях использования:

Кроме того, Aircall не рекомендуется для массовых массовых вызовов (например, службы поддержки клиентов или центры обработки вызовов продаж обрабатывают более сотни одновременных вызовов).

Ситуация сейчас

Сегодня наша цель не изменилась: предоставить группам простую, гибкую и не требующую аппаратного обеспечения телефонной системы. Но наш целевой клиент другой: колл-центры, отделы продаж и более крупные компании.

С точки зрения бизнеса, мы просто изменили целевого клиента и стоимость нашего плана. Но техническое воздействие было совершенно другим: наша инфраструктура была совершенно не подготовлена ​​к этому массивному потоку данных, и UX нашего продукта оказался полностью нарушенным. В результате наши приложения начали казаться нашим клиентам медленными и отстающими: в целом они стали казаться неполноценными.

Например, после этого перехода крупные компании захотели импортировать свои базы данных контактов, то есть более 2 миллионов записей для обработки, сортировки, поиска и отображения. Или call-центрам, которым необходимо обрабатывать более 10 тысяч звонков в день, с 200 агентами, одновременно использующими приложение и выполняющими с ним операции. И, конечно же, каждое действие должно происходить в реальном времени.

Было определенно большой ошибкой не предвидеть такого массового использования, но мы так спешили поддерживать рост нашего бизнеса, что не обращали внимания на эту проблему. В начале 2016 года нам пришлось столкнуться с этим: наш продукт сломался. Пришлось строить заново, почти с нуля.

Как мы создаем сложные и мощные приложения

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

С технической стороны это означало запуск нового проекта с чистой и развивающейся кодовой базой, новыми концепциями и передовыми практиками, новым внутренним API, который может обрабатывать массивный рендеринг данных, и новым процессом развертывания.

Чтобы было понятно, нам нужно было перестроить следующие приложения:

  1. Панель управления - где администраторы могут устанавливать номера телефонов и приглашать товарищей по команде;
  2. Телефон - на котором операторы могут совершать / принимать звонки и управлять своей общей контактной книгой.

Чтобы усложнить задачу, мы хотели отправить каждый проект всем нашим клиентам за 3 месяца: это было непросто, зная, что в то время команда внешнего интерфейса состояла всего из 4 человек.

Приложение TypeScripted AngularJS

Мы сохранили AngularJS (1.5) по одной основной причине: мы его осваиваем. Мы наизусть знаем, как его использовать, как создать огромную базу чистого кода и как извлечь из этого максимальную пользу. Конечно, мы смотрели и на другие веб-фреймворки, такие как React и Ember, но мы не были в них уверены. Кроме того, в AngularJS легче нанять талантливых людей, чем в других фреймворках (по крайней мере, во Франции).

Мы хотели, чтобы наш код был масштабируемым, понятным и простым в обслуживании, и TypeScript был лучшим решением.

  • Он добавляет в ваш код статическую типизацию и наследование;
  • Он обеспечивает проверку ошибок во время компиляции, что очень важно для предотвращения ошибок до того, как они произойдут в вашем браузере;
  • Это полезно для поддержания вашей базы кода чистой и понятной для нескольких инженеров;
  • Его легко изучить, так как он имеет тот же синтаксис, что и JavaScript.

Я почти уверен, что мы используем только 60% функций TypeScript, но это сэкономило нам десятки часов кода, предотвратило сотни ошибок и упростило управление нашими приложениями с инженерной точки зрения. Да, мы должны сказать это: хорошая работа, Microsoft.

Создан с помощью Webpack

Webpack - это сборщик модулей. Он берет все ваши файлы и зависимости и собирает их в один файл, который вы можете разместить на своем сервере. Поставляется с множеством мощных плагинов (полный список здесь). Мы настраиваем Webpack для:

  1. Скомпилировать код TypeScript в JavaScript;
  2. Внедрить все зависимости (AngularJS и прочее);
  3. Уменьшить в одном файле и уточнить JS-код;
  4. Скомпилировать и минимизировать код SASS в CSS;
  5. Подготовьте файлы GZiped.

Обратите внимание, что мы не использовали ни Bower, ни какие-либо инструменты кикстартера проекта, такие как Yeoman и Mimosa. Мы думаем, что чем меньше инструментов вы используете, тем легче будет поддерживать ваш проект.

Постоянно тестируется с CircleCI

Нам нужна была среда непрерывной разработки для создания, тестирования и развертывания наших приложений во всех различных средах.

CircleCI - это инструмент непрерывной интеграции и доставки SaaS, такой как Codeship или Jenkins. Когда мы помещаем код в ветку Git, CircleCI запускает виртуальный контейнер, клонирует в него репозиторий и выполняет определенный набор инструкций. Имея это в виду, мы настраиваем CircleCI для:

  1. Создайте приложение с помощью Webpack;
  2. Lint наш код TypeScript (TSLint) и наши файлы Sass (sass-lint). Правила, которые мы определили, немного грубоваты, но позволяют нам иметь уникальный стиль кода для всех нас;
  3. Запустите наш набор тестов. Пока пишутся только сквозные тесты с использованием Транспортира;
  4. Создайте новую версию CodeDeploy и разверните ее в AWS (см. Раздел ниже).

Если один шаг завершится неудачно, сборка остановится, и код не будет развернут на наших серверах. Если все в зеленом цвете, значит, мы только что развернули новую версию менее чем за 5 минут :).

Развертывается на инстансах AWS благодаря CodeDeploy

После создания приложения CircleCI создаст zip-файл, содержащий скомпилированные ресурсы вашего приложения, и загрузит его в корзину Amazon S3. Затем CodeDeploy автоматически обнаружит эту новую версию вашего приложения и установит ее на инстансы Amazon EC2. Поскольку наши приложения представляют собой статические ресурсы, установка CodeDeploy выполняется просто:

  1. Установите nginx, если его еще нет в экземпляре;
  2. Удалить файлы предыдущей версии приложения;
  3. Разархивируйте zip-файл S3 на сервере и переместите все эти скомпилированные файлы в папку / www / app_name;
  4. Настройте nginx с правильным сертификатом SSL и конфигурацией;
  5. Перезагрузите nginx.

Конечно, во время установки серверы отключаются от вашего балансировщика нагрузки по одному, поэтому ваше приложение не простаивает.

Приложения CodeDeploy могут иметь несколько групп развертывания: виртуальные группы с определенной ролью и конфигурацией - мы используем их для разделения нашей промежуточной и производственной сред. В нашей настройке каждая группа развертывания имеет два связанных экземпляра EC2, и эти серверы находятся за балансировщиком нагрузки (Amazon ELB). Более подробную информацию о CodeDeploy вы найдете здесь.

CircleCI имеет встроенную интеграцию CodeDeploy, которую довольно легко настроить. Это сэкономит вам время, так как вам не придется самостоятельно писать сценарии развертывания S3 и перехватчики.

Рендеринг приложений с помощью Nginx

Что действительно удобно при настройке Nginx при развертывании каждого приложения, так это то, что вы можете иметь конфигурацию Nginx в своей кодовой базе, и она будет автоматически обновляться на ваших серверах каждый раз, когда вы развертываете новую версию. Нет необходимости использовать ssh на каждом экземпляре, чтобы настроить новую конфигурацию Nginx. Вы можете подумать, что это излишне, но это сэкономит вам много времени, если вы добавите совершенно новый экземпляр в свою группу развертывания CodeDeploy.

Поскольку Webpack ранее создавал файлы gziped, нам просто нужно было разрешить gzip в нашей конфигурации nginx для файлов JavaScript и CSS. Не пропустите этот шаг, он значительно сокращает время рендеринга вашего приложения: только благодаря этому мы перешли из скомпилированного файла JavaScript размером 1,6 МБ в файл размером 300 КБ.

И последнее: мы используем Nginx только для рендеринга статических файлов, таких как HTML, CSS, JavaScript и изображений. Когда конечный пользователь переходит по URL-адресу нашего приложения, нет ничего, кроме Nginx, отображающего базовый файл index.html, который загружает необходимые ему ресурсы: просто :) Нет необходимости в NodeJS, Ruby или каком-либо другом сервере. .

И чертовски хорошая команда

Чтобы помочь вам создать лучшее приложение, вам понадобится команда талантливых умов. Люди, которые не будут спать, пока не найдут лучшее решение по продукту. Те же люди, которые будут чесать затылок, чтобы найти хоть какое-то улучшение скорости, а на следующий день придут в офис с воплем: «ГВОЗДИ!». И набор таких людей может оказаться самым сложным делом, которое вам придется сделать.

В Aircall мы только что завершили нашу самую большую задачу в команде: воссоздать с нуля оба интерфейсных приложения и улучшить их, чтобы сделать их пуленепробиваемыми. Самое лучшее еще впереди, поскольку все больше и больше компаний начинают использовать Aircall каждый день. Нам всегда нужно будет улучшать время загрузки, логику в реальном времени, добавлять новые привлекательные функции или изобретать новый способ обработки телефонных звонков. Хорошая новость в том, что мы продолжим делать это, пока не выбросим в мусор все старые черные телефоны Cisco, стоящие на столах компаний.

TL;DR

  • Приложение AngularJS, написанное на TypeScript и построенное с помощью Webpack
  • Протестировано и развернуто с CircleCI и CodeDeploy, размещено на экземплярах AWS за балансировщиком нагрузки.
  • Nginx как веб-сервер, рендеринг только HTML и ассетов
  • Много пота, сотни часов напряженной работы и впечатляющая командная работа. Поздравляем Maïa, Marc, Maxence и Gi!

Конечно, его можно улучшить, но для нас это самый простой в настройке, самый элегантный и продуктивный рабочий процесс разработки приложений, с которым мы хотели работать :)

Здравствуйте,
Ксавье