Короткая история о том, как облегчить жизнь разработчикам интерфейса при работе с шаблонами электронной почты

вступление

Мы в Травикс работаем в сфере туризма — продаем авиабилеты и сопутствующие услуги. Нашим клиентам нужны хорошие, полезные электронные письма. Когда вы путешествуете, иногда в аэропорту нет интернета или другие условия препятствуют использованию вашей учетной записи/приложения. Таким образом, надежное решение для получения информации о вашем рейсе действительно важно, а электронная почта — это старая школа, но проверенная временем технология.

Многие компании используют простые и небольшие электронные письма, чтобы предоставить минимальную информацию о действиях или даже просто ссылку на страницу профиля. Нам нужно отправить более богатый контент. Нам нужно предоставить информацию о рейсах, аэропортах, терминалах, времени трансфера. Мы также показываем информацию о пассажирах, их предпочтениях в еде, багаже ​​и местах. Кроме того, цены, отели или арендованные автомобили и важная информация от авиакомпаний. И поскольку мы выиграли RedDot design award, мы стремимся представить эту информацию в идеальном визуальном виде.

Условия

Со стороны внешнего интерфейса работа с электронной почтой — это ад.

Многие устаревшие клиенты напоминают мне о временах IE6. Некоторые не поддерживают display: none,другие не поддерживают пользовательские шрифты или вообще не отображают вашу электронную почту, третьи клиенты не поддерживают селекторы классов. И с этими условиями вам нужно разработать 12 типов красивых и блестящих адаптивных писем для 5 разных брендов в их собственных цветовых схемах для 20 языков.

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

Тестирование

Перед началом рефакторинга мы решили покрыть наши письма дополнительным тестированием.

Сначала мы начали пользоваться услугой Литмус. Вы можете проверить, как выглядят электронные письма в разных клиентах на разных платформах: таких как Android, iOS, MS Outlook, Gmail, почта Yahoo и многих других. Этот сервис имеет хороший API, поэтому можно даже автоматизировать создание изображений для электронных писем.

Во-вторых, мы начали использовать тесты визуального сравнения с BackstopJS. Эта библиотека отображает HTML-страницы с помощью phantomJS в различных разрешениях экрана и сохраняет скриншоты в качестве ссылки. После первоначального рендеринга вы вносите некоторые изменения и снова запускаете тесты визуального сравнения.

BackstopJS использует алгоритм сравнения изображений, и если различия между созданным изображением и эталонным изображением превышают пороговое значение, он не проходит тест и открывает браузер, показывающий изображения неудачных тестовых случаев. Основная проблема здесь заключается в том, как шрифты отображаются (по-разному) на разных машинах. Если вы храните в своем репозитории эталонные изображения, созданные на macO, тесты не будут выполняться на компьютере с Linux, и наоборот. Поэтому мы решили хранить не изображения, а просто снимки в формате HTML и каждый раз генерировать эталонные изображения из этих снимков, чтобы видеть только значимую разницу.

Визуализация

Следующим, что облегчило нам жизнь, стала библиотека — JuiceJS. Он автоматически встраивает стили в HTML из CSS.

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

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

Сначала мы пытались использовать Handlebars, но быстро поняли, что у него много ограничений. Поэтому мы решили использовать React с рендерингом на стороне сервера. В результате мы также получили чистый поток данных с проверкой PropTypes и поддержкой ESLint для шаблонов.

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

Стили

Последний вопрос был о стилях. Раньше у нас был весь CSS в одном файле, что было не очень удобно. Мы проверили некоторые решения для SASS или PostCSS, но им требовался веб-пакет или другие инструменты для сборки по каждому запросу (что слишком много накладных расходов), и у нас по-прежнему было одно глобальное пространство имен. Поэтому мы решили использовать CSS-модули, чтобы пространство имен каждого компонента оставалось локальным, и помимо CSS-синтаксиса мы использовали простые строки JS-шаблона для вставки переменных (в основном цветов) из текущей темы.

Вывод

С переходом на React и CSS-модули мы значительно ускорили процесс разработки. А тестирование с Litmus и Backstop помогло уменьшить визуальную регрессию. Но все же работать с шаблонами писем не так просто и гладко из-за ограничений почтовых клиентов. И никто не жалуется на это по неизвестной причине.

Полезные ссылки

*или, по крайней мере, менее болезненно