1. Обзор
  2. Контекст и проблемы
  3. Рабочая обстановка
  4. Технические решения
  5. Результаты
  6. Последние мысли

Обзор

Привет, я Себастьян. Я работаю в busuu ведущим Front-end инженером. busuu - компания, занимающаяся изучением языков, наша миссия - помочь каждому выучить новый язык. У нас есть Backend-команда, которая предоставляет API-интерфейсы для остальной технической команды, веб-команда, которая занимается 3 различными веб-приложениями, и команды iOS / Android, которые работают над нашими мобильными приложениями.

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

Контекст и проблемы

В этом тематическом исследовании основное внимание уделяется интерфейсу busuu.com, где мы обрабатываем регистрации, входы / выходы и все потоки платежей, а также все информационные страницы, чтобы помочь пользователям понять, что мы делаем и как мы это делаем.

Одной из самых больших проблем, которые нам пришлось преодолеть, была производительность. Старая платформа загружала более 150 КБ CSS, 160 КБ JavaScript, а время загрузки страницы занимало около 3 с. Было сделано более 90 HTTP-запросов, и было загружено много ресурсов.

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

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

Рабочая обстановка

Gulp как исполнитель задач

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

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

Мы решили не использовать webpack, так как нам нужно было нечто большее, чем просто сборщик модулей JavaScript. Нам нужна была гибкость, поскольку этот проект имеет разные аспекты зависимостей, чем одностраничное приложение.
Мы все знали Gulp в команде и решили перейти на Gulp, потому что он быстрее, чем Grunt (в основном для Sass), и потому что у всех был в прошлом работал с Gulp. Мы рассмотрели решение на основе сценариев npm, но нам не очень хотелось писать наши задачи в package.json. По моему личному мнению, это будет следующий вариант, который я без колебаний изучу дополнительно в предстоящем проекте.

Поиск подходящей CMS

Нам нужна была CMS для размещения наших страниц, и мы хотели, чтобы она работала быстро, но при этом не требовала особого обслуживания и обеспечивала приятный интерфейс для нашей маркетинговой команды. Я всегда работал в компаниях, где у нас была собственная система управления контентом, поэтому нам нужно было найти лучшее решение для busuu, и мы начали с изучения ряда генераторов статических сайтов.

Нам нужна была CMS, которая позволяет нам создавать нашу собственную тему, иметь 100% гибкость в отношении выходного кода и, что более важно, иметь панель администратора, которую люди без технических знаний могут использовать для создания контента. Нам также нужен был полный доступ к страницам из CMS по причинам SEO, например, чтобы иметь возможность динамически обновлять «‹titles›« или метатеги.

После нескольких попыток Джекилла или Хьюго мы выбрали Grav. это современная CMS с открытым исходным кодом, работающая с плоскими файлами. Все основано на файлах разметки и за кулисами, и это полезно на основе PHP, поскольку это основная технология, используемая в наших API. Даже если вы не являетесь разработчиком PHP, вы можете легко перейти на Grav, я очень рекомендую это.

Sass как препроцессор CSS

Мы выбираем Sass для обработки нашего CSS, поскольку сегодня нет большого выбора препроцессоров CSS, у Sass огромное сообщество и он хорошо интегрирован с Gulp. Мы используем Sass по нескольким причинам:

  • Это позволяет нам разделить наше приложение на разные файлы .scss для создания компонентов, модулей и макетов.
  • Наши файлы `.scss` легче читать и легче поддерживать, чем один файл app.css.
  • Мы можем использовать миксины и переменные.
  • Мы можем создавать или владеть функциями.
  • Избегаем дублирования кода.
  • Мы можем легко настроить различные конфигурации в Gulp (локальный / производственный).

Browserify как сборщик модулей JavaScript

Нам нужен был сборщик модулей, который позволяет нам экспортировать / импортировать модули в JavaScript с инкапсуляцией кода. Browserify - это довольно безопасный выбор сегодня, если вы хотите организовать свой код по компонентам, как это делаем мы с Sass.

Это позволяет нам создавать файлы ввода, а затем импортировать другие модули JavaScript в качестве зависимости. Затем Browserify получит первый файл записи, проследит за каждым импортированным файлом из каждой зависимости и затем выведет один файл `.js`. Даже если вы импортируете один и тот же сценарий 10 раз, Browserify импортирует файл один раз. Очень кстати.

Browserify работает с node, и одна из самых больших особенностей Browserify заключается в том, что вы можете использовать большую часть всех библиотек и функций node. По этой причине мы можем экспортировать / импортировать наши модули JavaScript с помощью метода require ();.

Последняя причина, и это действительно важно, когда вы имеете дело с партнерами, Browserify выполняет инкапсуляцию кода, поэтому в объект окна ничего не экспортируется. Это безопасный способ быть на 100% уверенным, что внешний скрипт не перезапишет ваши переменные JavaScript.

Babel как компилятор JavaScript

Мы начали писать наши модули JavaScript на ES6. Babel - это компилятор ES6 в ES5, он используется Facebook, и сегодня его используют многие библиотеки и компании. Он довольно прост в использовании и хорошо интегрируется с Browserify.

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

Crowdin как платформа управления локализацией

Наша платформа поддерживает 15 языков, а реализация определения языка осуществляется Grav. Переводы выполняются во Front-end, у нас есть файл .yaml, в котором перечислены все строки, используемые на платформе.

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

После установки Crowdin вы можете легко загружать / скачивать / удалять новые переводы с помощью команды bash с помощью Crowdin Client Tool.

Технические решения

Структура CSS

Когда мы запускали проект, мы стремились иметь один статический файл (`.css` и` .js`) на страницу, так как мы хотели избежать загрузки стилей страницы оплаты, например, на домашней странице. Это одна из причин, почему CSS-файл новой домашней страницы после сжатия Gzip весит 7,8 КБ.

Что касается производительности, также рекомендуется не иметь нескольких статических ресурсов (CSS / JS) на одной странице.

Что касается организации кода, мы разделяем наше приложение на компоненты, модули и макеты. За этим стоит идея философии атомарного дизайна Брэда Фроста. Компоненты строит Модули, Модули строит Макеты.

Вот скриншот нашего текущего репозитория стилей в Github:

CSS Unit

Мы решили использовать блок REM в качестве основного блока CSS. REM относится к корню документа (тег `‹html›`). Это означает, что каждое свойство CSS теперь привязано к текущему параметру font-size в браузере пользователя и ничего не фиксируется в пикселях. Если пользователь решит изменить размер шрифта своего браузера на «Большой», размер нашего приложения увеличится вдвое. Я действительно рекомендую вам взглянуть на REM, если вы еще этого не сделали.

На следующих снимках экрана показана разница между busuu.com в REM и busuu.com в PX, когда пользователь добровольно изменил размер шрифта по умолчанию.

Соглашение об именах CSS

В busuu мы стараемся максимально использовать БЭМ. БЭМ - это соглашение об именах в CSS, которое снижает специфичность вашего CSS. Идея состоит в том, чтобы получить один селектор CSS для данного элемента, а не больше. Тогда будет проще переопределить селекторы, а также повысится читаемость кода.

Единственный недостаток БЭМ, который я обнаружил, состоит в том, что он немного загрязняет HTML, поскольку создает длинные имена классов. По этой причине мы не слишком сильно продвигаем методологию БЭМ. Иногда, когда элемент находится глубоко в DOM и уже привязан к блочному элементу БЭМ, мы просто используем классический способ написания нашего CSS с использованием каскадирования, например:

.header__picture .icon {}

Шрифты

Мы используем шрифты, они улучшают дизайн и выделяют ваш бренд. Но шрифты тяжело загружаются и создают Flash of Invisible Text (FOIT - текст скрыт до загрузки шрифта). Если вам важна производительность, важно контролировать, как и когда загружаются шрифты. Исходя из моего предыдущего опыта, мы использовали логику, используемую в Smashing Magazine для загрузки наших шрифтов.

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

Мы решили попросить наших дизайнеров изменить дизайн busuu.com с использованием не более двух шрифтов. В 2017 году загрузка шрифтов улучшилась: мы используем инструмент Font Face Observer от Bram Stein. Это действительно похоже на трюк Smashing Magazine, но улучшено. Он будет отслеживать применение веб-шрифта к странице и уведомлять вас. Это также исправляет некоторые проблемы, которые были у техники Smashing Magazine в прошлом.

Отзывчивый и точки останова

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

$mq-small-bp: 31.25em; // below 500px: smartphones, small devices
$mq-medium-bp: 50em;   // below 800px: big smartphones, small tablets
$mq-large-bp:  75em;   // below 1200px: big tablets, laptop, standard screens

Почему? Потому что теперь вместо того, чтобы пытаться целиться в iPhone или iPad, вы вместо этого сосредотачиваетесь на определенной области ширины устройства. Затем вы можете охватить ряд устройств, которые будут доступны сегодня и в будущем. И если вам нужна дополнительная точка останова, вы все равно можете добавить ее для определенного модуля.

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

Мы постарались максимально сократить код, который у нас есть внутри медиа-запросов, потому что мы хотим сохранить байты, а также потому, что можно сначала создать гибкие макеты. Мы создали компоненты и модули, которые автоматически адаптируют свою ширину (в%) к текущей ширине контейнера. Когда это было невозможно, нам на помощь приходила точка останова.

Адаптивный макет можно улучшить (например, с помощью меню вне холста на экране смартфона), это не первая функция, на которой мы сосредоточились, но теперь любой, кто получает доступ к busuu с небольшого устройства или планшета, может легко получить доступ к сайту.

Результаты

После того, как мы удалили старую платформу PHP, отложили загрузку шрифтов, минимизировали наши CSS и JavaScripts, использовали SVG и сократили количество HTTP-запросов, пришло время протестировать.

Мы следовали правилам, рекомендованным Google, чтобы максимально оптимизировать рендеринг страниц, и постарались применить лучшие практики для повышения производительности страницы. К сожалению, поскольку нам приходится иметь дело со скриптами отслеживания партнеров, мы не можем применять все правила на 100%.

Мы провели множество тестов с помощью инструмента PageSpeed от Google и WebPageTest. И результаты стоили того, чтобы потратить время на этот редизайн. Мы почти разделили событие DOMContentLoaded на 3, с ~ 1,5 с до ~ 300 мс. Загрузка страницы также улучшилась, со средней загрузки ~ 3 с до менее чем ~ 500 мс.

Только Европа. В настоящий момент серверы находятся в Европе.

Мы также уменьшили количество HTTP-запросов с ~ 90 до ~ 40. Наконец, общий вес страницы теперь составляет ~ 1,1 МБ вместо ~ 1,8 МБ .

Оценка PageSpeed ​​теперь лучше - мы все еще можем улучшить, но, по крайней мере, мы сделали то, что можно было улучшить. Последний бит в основном связан со скриптами партнеров и из-за CSS «‹link›« в голове.

Последние мысли

Стоило ли? Определенно - но не так быстро. В нашем случае было очевидным перестроить наше приложение, потому что первым требованием было наличие CMS, где наша маркетинговая команда могла бы создавать и управлять контентом. Наш сайт также был ужасно старым и беспорядочным - иногда полная перестройка стоит усилий, а не попытки рефакторинга устаревшей платформы.

Я не говорю, что вы всегда должны перестраивать с нуля, иногда простой пошаговый рефакторинг кода может дать отличный результат и сэкономить много времени.

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

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

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

Спасибо, что прочитали. Если у вас есть вопросы, оставьте комментарий!
Вы также можете найти нас в Twitter: @busuuTech и @SebastienAxinte

И если это звучит великолепно, вы хотите продвинуться в своей технической карьере и любите изучать языки (технические или другие!), У нас есть много открытых должностей в нашей Технической команде!