
Отказ от ответственности 1: я действительно считаю себя довольно молодым во внешнем интерфейсе, на самом деле я парень из бэкенда, поэтому я специально хотел спроектировать интерфейсную часть, чтобы узнать больше о новых стеках и (возможно) лучше понять интерфейс сообщество.
Так что если у вас есть идеи, предложения, исправления и т. д., дайте мне знать об этом!
Инфраструктура
Я решил реализовать каждую часть потока сайта в отдельном веб-приложении по следующим причинам:
- Попробовать разные фреймворки или провести рефакторинг реализации выбранного в каждом новом приложении.
- Чтобы сохранить как минимум кодовую базу каждого приложения.
- Отказоустойчивость и быстрое развертывание.
Кроме того, если бы мы использовали отдельные приложения вместо SPA, нам не пришлось бы жертвовать пользовательским интерфейсом (по крайней мере, не сильно), поэтому в тот момент это выглядело как хороший подход.
Затем я разделил сайт на следующие клиентские приложения:
- Дом
- Результаты рейсов
- Перенаправление кассы
И каждое веб-приложение выглядело так:

Фреймворк Frontend

На момент начала разработки внешнего интерфейса у меня не было опыта работы с какой-либо недавней инфраструктурой или библиотекой внешнего интерфейса, последний раз, когда я кодировал приложение внешнего интерфейса, был просто jQuery и замыкания.
Я начал читать различия между ними основные фреймворки того времени: Angular 2 и React + Redux. Наиболее частый вывод опытных людей, который я читал, был: «Вы можете использовать любой из них, и вы, вероятно, достигнете тех же целей, но Angular 2 гораздо более самоуверен».
Имея это в виду, я выбрал Angular 2 на В начале, в конце концов, это был один из основных фреймворков, и в нем было сделано много вариантов, иначе говоря, менее «трудные» решения, которые нужно было принимать с моим плохим опытом работы с веб-интерфейсом.
Затем я просмотрел несколько руководств и начал писать код, но… вскоре после этого я обнаружил несколько проблем:
- Рамки менялись почти каждую неделю.
- След был огромным.
- Горячая перезагрузка в браузере прошла далеко не гладко.
- Я не смог найти некоторые базовые компоненты в сообществе разработчиков ПО с открытым исходным кодом (например, средство выбора диапазона дат).
- Сильная связь логики моего компонента с реализацией фреймворка. например специальный код для компиляторов AOT и JIT.
- И т. Д. И т. Д. И т. Д.
В то время я попробовал React, и это было действительно великолепно, действительно, я мог написать целый пост с очень вескими причинами, чтобы выбрать React в качестве своего внешнего фреймворка.
Теперь все фронтенд-приложения TF - это в основном React + Redux + Webpack, и все. Больше никаких глотков или браузеров.
Попробовав оба, Angular 2 и React, я продолжу основное различие, которое я обнаружил, следующим образом:
По шкале сложности от 1 до 10, где 1 - это купить кофе в Starbucks, а 10 - организовать убийство Дональда Трампа: код приложения React - это 3, а кодирование приложения Angular 2 - 6.
Заявление об ограничении ответственности 2: я выбрал стек внешнего интерфейса примерно в середине 2016 года. Я знаю, что с тех пор в Angular были внесены некоторые улучшения, но даже сегодня я бы снова выбрал React!
Скорость
Мы решили сфокусировать наш сайт на увеличивающемся мобильном трафике, но мы находимся в Аргентине, и скорость мобильных сетей не самая лучшая. Покрытие сети LTE очень ограничено, а производительность сети 3G очень низка.
Затем, чтобы предоставить пользователю лучший опыт, нам нужно было создать действительно быстрый сайт, и вот некоторые из вещей, которые мы сделали :
HTTP2
И ALB (балансировщик нагрузки AWS), и Cloudfront (AWS CDN) работают с HTTP2, поэтому реализовать это было несложно. Я не собираюсь делать полный обзор HTTP2 в этом посте, но просто используя HTTP2, мы получаем следующие возможности:
- Большое количество одновременных подключений для каждого домена (это очень важно для статического контента).
- Сжатые заголовки (это очень важно для файлов cookie).
Сжать все
Вы можете легко сделать это с помощью Nginx. Кроме того, вы можете внести очень хитрые улучшения, используя модуль скорости страницы. Я сделал очень простой образ докера Pagespeed, чтобы попробовать, но, в конце концов, я не использовал какой-либо фильтр, потому что он не дал нам никакого улучшения производительности, и я увидел в этом опасную связь.
Функции Squeeze Webpack

Код нашего приложения менялся каждый день, но не библиотеки, которые мы использовали. Я разделил код приложения сторонних зависимостей на два разных пакета. Таким образом, мы воспользовались кешем браузера, потому что единственным новым активом при каждом развертывании был пакет de app.js.
Другими особенностями веб-пакета, которые я использовал, были:
- Проверяйте каждый актив с контрольной суммой.
- Отфильтруйте ненужные ресурсы, например все локали momentJs, которые мы не использовали.
- Сократите код js каждого пакета.
- Используйте модули css, сохраняя кристально чистый код sass для каждого компонента.
Чтобы протестировать многие из этих функций, я использовал BundleAnalyzerPlugin, который дал мне представление об окончательном размере каждого пакета js и его составе.

CDN
Я решил обслуживать весь статический контент через Cloudfront. С помощью серверов пограничного местоположения мы снизили среднюю задержку на 75%. У нас есть инфраструктура только в регионе us-east-1, поэтому для нас очень важно, чтобы местоположения CDN были близки к источникам запросов по всему миру.
Мы версируем все наши ресурсы и храним их в кэше в браузере, используя только одно исключение: файлы HTML. Однако мы храним их в кеше CDN с помощью http-заголовка cache-control: s-maxage = 2592000, который указывает, что ресурс может храниться в общих кешах, таких как прокси или CDN.
Таким образом, мы сохраняем низкое время отклика даже для первого из когда-либо обслуживаемых ресурсов - домашней страницы html. Для этого необходимо сделать недействительным кеш HTML-файлов, обслуживаемых определенным приложением, когда мы выполняем новое развертывание этого приложения.

Одним из ограничений Cloudfront является то, что на момент написания этой статьи он не поддерживает HTTP2 server push = (.
Устранение обратных поездок с помощью preconnect
Еще я оптимизировал время для загрузки ресурсов из разных доменов, таких как домен gtm или наш домен static.travelfighter.com, в котором есть общие ресурсы, такие как логотипы, фоны, значки и т. Д.
Если вы этого не сделаете, сделайте это! Используйте тег в HEAD вашего html, например:
‹link rel =” preconnect ”href =” https: //static.travelfighter.com'/ ›
Браузер:
- Разрешает имя DNS.
- Выполняет квитирование TCP.
- Согласовывает туннель TLS
И это может сэкономить пару сотен миллисекунд при загрузке ресурсов из нового домена.
Мониторинг эффективности
Это, пожалуй, самое важное, что нужно сделать, когда вы хотите повысить производительность своего сайта и принять правильные решения. Первым инструментом, который я использовал, был webpagetest site, и через некоторое время я автоматизировал мониторинг производительности с помощью инструментов sitespeed.io, запланировав такие очень простые задания, как это:

Вы можете использовать серверы webpagetest по всему миру (или на своих серверах) для запуска тестов производительности вашего сайта, имитируя настраиваемую полосу пропускания и задержки подключения. Затем вы можете хранить показатели в Graphite и визуализировать их, а также создавать настраиваемые оповещения в Grafana.

—
После множества настроек мы достигли прекрасной производительности в 1,6 секунды, чтобы визуально укомплектовать наш дом кабельным соединением из Буэнос-Айреса и со всего мира, тратя всего пару долларов каждый месяц. знак равно
Мониторинг ошибок в браузере и на стороне сервера
И для серверной (nodeJs), и для клиентской (браузеры) стороны мы используем бесплатные инструменты.
На стороне сервера мы используем старый добрый APM NewRelic в сочетании с метриками NewRelic Servers, чтобы получить много информации о приложениях, контейнерах докеров и хостах.
На стороне клиента мы используем Sentry, который имеет множество интеграций с разными языками и фреймворками. Мы используем redux-raven-middleware, чтобы видеть каждое действие, такое как хлебная крошка, и все состояние redux при возникновении ошибки.
Для предупреждений мы используем канал Slack для получения уведомлений как от NewRelic, так и от Sentry.
Создание интерфейса было определенно одной из самых увлекательных вещей, которые я делал в TravelFighter. И, повторяю, я новичок в этом, поэтому, если у вас есть какие-либо идеи, предложения или исправления, сообщите мне об этом!
