Вы, возможно, слышали, что мы начали использовать React в производстве более года назад в NFL. Если вы тоже его использовали, то знаете, что за это время многое изменилось: React перешел с версии 0 на 15 (не совсем, но на самом деле), React Router представил динамическую маршрутизацию, встроенные стили. вошел в нашу коллективную благосклонность после многих лет в собачьей будке, и экосистема React в целом росла семимильными шагами. Сказать, что это был захватывающий год, было бы преуменьшением.

Конечно, это волнение не обошлось без головной боли. Веб-команда NFL поддерживает девять проектов React в одном монолитном репозитории. Как бы мы ни хотели, чтобы все они были блестящими и актуальными, просто невозможно (или разумно) прочесывать такой объем кода каждый раз, когда появляется новый синтаксис для ссылок или новая парадигма маршрутизации.

Это означает, что когда мы решаем пойти на это, мы делаем все сразу, как сдираем пластырь. Недавно мы объединили незначительные обновления за шесть месяцев в одну полную миграцию. Большинство изменений были небольшими и повторяющимися, например, изменение каждого тега ‹Link› для поддержки последней версии React Router или небольшое изменение всех наших стилей при переходе от Stilr к Radium. Дело в том, что обновления, которые нам нужно было сделать, не были большими или сложными, но они были повсюду.

Введите response-codemod

Вскоре после того, как мы начали тихую панику, мы наткнулись на проект Facebook под названием react-codemod. Время от времени React выпускает критические изменения в своем API, а response-codemod представляет собой серию скриптов, которые просматривают ваш код за вас и вносят необходимые обновления (технология, лежащая в основе этого, выходит за рамки этой статьи, но «это довольно круто").

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

Шаги малыша

Мы начали с малого: возьмем то, что можно исправить простым поиском / заменой, но обработаем это с помощью codemod. Первым предметом, который мы выбрали, была рана, нанесенная самому себе. У нас был открытый исходный код одной из наших библиотек (ура!), поэтому весь импорт пришлось изменить (boo) с @ nfl / gridiron / addons на реагировать-шлем.

Активизация

Когда у нас были первые несколько скриптов, пришло время поднять ситуацию на ступеньку выше. Ast-types, технология, лежащая в основе response-codemod, дала нам контроль над каждым аспектом нашего кода, от вызовов методов до декораторов ES7 до тегов и атрибутов JSX. Каждое новое открытие сопровождалось вздохом облегчения, поскольку большая автоматизация впереди означала меньше тяжелой работы в дальнейшем.

CSS classNames для встроенных стилей

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

// before (using the classNames library to combine classes)
<input className={classNames(styles.one, styles.two)} />

// after
<input style={{...styles.one, ...styles.two}} />

И код:

Обновление React Router

Мы также обновили React Router, что означало избавление от именованных маршрутов и переключение на внутренний помощник по маршрутам.

// before
<Link to=”superbowl” params={linkParams}>{game.year}</Link>
// after: route.for() is the internal helper we created
<Link to={route.for(“superbowl”, linkParams)}>{game.year}</Link>

Продолжая

Последний пункт, к которому мы должны были обратиться, связан с центральным элементом нашей новой архитектуры: jspm. Когда вы импортируете что-то в Node, вам не нужно быть слишком конкретным. Вы можете указать файл, каталог или внешний модуль, и Node выполнит несколько шагов, чтобы выяснить, что вы хотите импортировать. Это нормально, если вы используете инструмент связывания javascript, такой как Webpack, но jspm загружает каждый файл индивидуально через HTTP. Для нас это означало изменение всего нашего импорта с неоднозначного на явный.

На выполнение всех операций импорта в нашем коде вручную потребовалась бы целая вечность, но codemod упростил это. Мы просто захватили весь импорт из нашего собственного каталога / src (т.е. не пакетов узлов), а затем использовали модуль resolve для определения полного пути к файлу. Задача решена!

В ходе этого процесса мы также обнаружили ряд индексных файлов «псевдонимов», которые ничего не делали, кроме импорта и экспорта родственных файлов. Они были там ради того неоднозначного импорта, но теперь мы могли убрать код и вычислительные издержки, избавившись от них. Вы можете думать об импорте как о связанном списке A → B → C. Нам нужно было удалить B и указать прямо от A до C.

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

Убираться

Чтобы избавиться от этих лишних файлов, мы ввели инструмент под названием shelljs, который, как следует из его названия, переносит все ваши любимые команды оболочки в страну javascript. Это было полезно для удаления этих дополнительных индексных файлов и выполнения пары других задач по наведению порядка, таких как переименование наших файлов .jsx в .js для единообразия.

На этом миграция была завершена!

Последствия

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

Тем не менее, подавляющая часть работы лежала в золотом уголке где-то посередине, и с этими новыми инструментами автоматизации в нашем распоряжении мы сможем поддерживать наш стек в более актуальном состоянии, чем когда-либо. Прошли те времена, когда нужно было решать все вопросы миграции сразу; теперь мы можем управлять вещами более модульным способом по мере возникновения каждой ситуации (если бы этот термин еще не использовался, я бы назвал это подходом «непрерывной интеграции»).

Мы только что коснулись того, что можно сделать с помощью codemod и ast-types. Мы использовали их для переноса существующего кода, но нет причин, по которым они не могут пройти через ваш код и вырезать модульные тесты, настроенные в соответствии с вашими предпочтениями, или объединить их с eslint, чтобы очистить ваш код по мере его написания. Может быть, вам просто нужен сценарий, чтобы заменить все ваши изображения изображениями Леонардо Ди Каприо (на самом деле он готов, напишите мне, если хотите). Я хочу сказать, что этот список можно продолжать и продолжать, и мы очень рады видеть, где еще мы можем использовать этот недавно найденный набор инструментов.

Наш проект codemod можно посмотреть здесь, мы рекомендуем вам ознакомиться с ним!

Изображения являются собственностью (в указанном порядке) Paramount Pictures, New Line Cinema, Warner Bros. Pictures, 20th Century Fox