Автор Пол Суда

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

Как мы выбираем пакеты

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

Наши критерии оценки пакета включали: надежность документации; как недавно он был выпущен; насколько наши инженеры были знакомы с пакетами (большинство из них написали модульные тесты на Jasmine и разработали приложения на React); процветающая экосистема связанных пакетов NPM; и количество загрузок.

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

Локализация

Наша дорожная карта платформы включает расширение на несколько языков и форматов даты. В то время как многие фреймворки (например, Ruby on Rails) поставляются с набором инструментов для обработки переводов, а также форматирования даты и чисел, подход экосистемы пакетов NPM «раскрутите свой собственный» означает, что нам необходимо проводить исследования и экспериментировать.

Мы выбрали пакеты с наилучшим балансом между размером пакета и возможностью поддержки языков с наибольшей потенциальной базой пользователей. Мы оценили полифилл Intl.js, который имел гораздо более широкую поддержку большего количества локалей, но добавлял в сборку слишком много дополнительного кода и данных, чтобы быть практичным. Мы остановились на Numeral.js для форматирования числовых значений, и мы выбрали Moment.js для форматирования времени и даты.

Доступно множество пакетов NPM для языкового перевода, но многие из них не обновлялись более года или имеют очень маленькое количество загрузок. Мы выбрали Polyglot.js, потому что он находится в стадии активной разработки, поддерживается крупной компанией (Airbnb), хорошо документирован и обладает сильным пользовательским интерфейсом как для перевода копии текста, так и для поддержки переводов.

Поскольку мы собрали наше решение для локализации из трех разных пакетов и у нас было много компонентов, которые использовали бы все три, мы хотели загрузить их все сразу для повышения эффективности. Для этого мы создали небольшой файл в lib / locale.js, например:

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

Управление CSS

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

Итак, мы вошли в этот проект с мантрой «пишите как можно меньше CSS».

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

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

Инструменты разработчика

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

Для линтинга нашего кода ESLint был очевидным выбором из-за его популярности и поддержки таких функций React, как JSX, и мы используем Руководство по стилю Airbnb с некоторыми изменениями. Мы также создали собственное настраиваемое правило для поиска мест, где текст, который нужно перевести, появляется непосредственно в шаблонах и строках.

Для запуска юнит-тестов и отчетов мы используем Карма и Жасмин. Jasmine хорош тем, что поставляется с репортерами, сопоставителями, шпионами методов и определяет спецификации с помощью знакомых rspec-подобных методов it () и описать (). Karma легко запускает тесты в автономном браузере в CI и в настольном Chrome для локальной разработки.

Это был первый проект Javascript, в котором мы стремились обеспечить 100% тестовое покрытие, поэтому мы создали Стамбул, чтобы помочь нам добиться этого. Для сегментов кода, где тестирование просто не имеет смысла, мы можем игнорировать покрытие, добавив комментарий в строке выше / * istanbul ignore next * /.

Кодирование инструментов Istanbul с использованием плагина для Babel, который добавляет много дополнительного кода к сгенерированному набору ресурсов. Что касается размера пакета и производительности, важно избегать инструментария производственного кода. Пример из нашего webpack.config.js, который справляется с этим:

Мы решили попробовать Flow, инструмент, который добавляет проверку типов (ограниченным образом) в Javascript и, как известно, хорошо работает с приложениями React. Это краткий способ выразить то, что мы делали в прошлых проектах с помощью React PropTypes. Нам нравится не импортировать PropTypes из prop-types в каждом компоненте, а нотация, которую он использует для помещения типов в определение класса, более четкая.

Пример использования Flow:

Задачи НПМ

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

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

При локальной работе с кодом мы можем запустить npm run unit-test-watch для непрерывного модульного тестирования нашего кода по мере его изменения. У нас есть задачи npm run lint и npm run unit-test для линтинга и тестирования в неинтерактивном режиме, а также задача npm test, в которой мы запускаем CircleCI для каждого запроса на вытягивание, чтобы убедиться, что он строится.

Сделайте это с самого начала

Чтобы убедиться, что все работает правильно, самым первым, что мы создали, была страница «hello world», которая просто отображала текст «hello world» в минималистичном макете. Но он сделал это с надлежащей локализацией, был полностью переведен, полностью протестирован со 100% покрытием, соответствовал нашим стандартам кодирования и использовал правильно сформированные компоненты React.

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

Экономия времени или отнимает много времени?

Выполнение дополнительной работы по поддержке всего в начале проекта в конечном итоге сэкономило нам время. Конечно, наш первый спринт был потрачен на реализацию роскошной версии «hello world». Но скорость после этого спринта была значительно увеличена, и трата спринта с упором на правильную настройку проекта помогла нам с самого начала сформировать хорошие привычки.

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