- PVSM.RU - https://www.pvsm.ru -

Почему в основе каждого нового веб-приложения в PayPal лежит TypeScript?

Недавно мы опубликовали материал [1], в котором Эрик Эллиот критиковал TypeScript. Сегодня мы представляем вашему вниманию перевод статьи Кента Доддса. Тут он рассказывает о том, почему в PayPal перешли с Flow на TypeScript.

image [2]

Предыстория

Я работаю в PayPal и занимаюсь библиотекой paypal-scripts, которая представляет собой набор инструментов, напоминающий react-scripts из create-react-app, или angular-cli, или ember-cli. Об этом я уже писал [3]. В основе этой библиотеки лежит идея объединения всех инструментов, используемых в приложениях PayPal и в опубликованных модулях. Цель создания paypal-scripts заключается в том, чтобы взять все зависимости разработки, devDependencies, из package.json, все конфигурационные файлы, и свести всё это к одной записи в разделе devDependencies. И, так как все конфигурации находятся в единственном пакете, при создании которого придерживаются вполне определённой точки зрения на то, «что такое хорошо», для того, чтобы поддерживать инструменты в актуальном состоянии, достаточно обновить лишь одну зависимость (собственно — paypal-scripts), обновления которой обычно не содержат в себе чего-то такого, что способно нарушить работу кода, полагающегося на неё. В результате достаточно поддерживать в актуальном состоянии лишь одну зависимость и спокойно заниматься разработкой приложений.

За последний год программисты в PayPal привыкли работать с paypal-scripts. Здесь для создания нового приложения достаточно щёлкнуть по нескольким кнопкам в веб-интерфейсе, в результате чего будет создан корпоративный GitHub-репозиторий, будут настроены средства развёртывания проекта, система непрерывной интеграции, и так далее. Автоматически создаваемый репозиторий основан на репозитории sample-app.

Буквально на прошлой неделе в него было включено моё добавление, рассчитанное на использование в нём paypal-script. Это означает, что в основе каждого нового приложения в PayPal будет лежать каркас, построенный на базе современных технологий и инструментов, об обновлении которых не нужно заботиться разработчику этого приложения. Кроме прочего, подобное приложение будет статически типизировано с использованием TypeScript и протестировано средствами Jest.

Честно говоря, это стало Magnum Opus моей карьеры. Я не думал, что когда-нибудь мне удастся достигнуть подобного уровня в PayPal. Этот проект оказывает огромнейшее влияние, и я благодарен PayPal за то, что мне предоставлена возможность работать над чем-то столь масштабным.

Так, в курс дел я вас ввёл, теперь поговорим о TypeScript.

В середине декабря я работал над тем, чтобы интегрировать paypal-scripts в sample-app. Ещё я работал (и продолжаю работать) над проектом pp-react, который представляет собой библиотеку компонентов (кнопок, окон, стилей), подходящих для повторного использования. Так как paypal-scripts поддерживает модули, которые могут быть опубликованы, я, для сборки pp-react, использовал react-scripts. Месяц тому назад библиотека paypal-scripts включала в себя поддержку Flow [4]. Такую поддержку было очень просто добавить в эту библиотеку благодаря Babel.

12 декабря, когда я работал над pp-react и новой версией sample-app в плане поддержки Flow, я почувствовал, что от Flow я уже очень устал (подробнее об этом я расскажу ниже) и принял неожиданное решение. Я написал коллеге [5] письмо, спросив его о том, как он смотрит на то, что я попытаюсь сделать так, чтобы в sample-app использовался бы TypeScript. Он ответил: «Да, сделай». Тогда я устроил опрос на Slack-канале #paypal-scripts, по результатам которого оказалось, что мою идею поддерживают все его участники. Для меня всего этого было достаточно для того, чтобы приступить к работе. Примерно через неделю я полностью перевёл paypal-scripts с поддержки Flow на поддержку TypeScript. Большая часть этого времени ушла на то, чтобы научить все инструменты распознавать расширения файлов .ts и .tsx, и на то, чтобы позволить пакету paypal-scripts самому себя протестировать, что оказалось довольно-таки непростым делом. Потом я потратил несколько дней на работу над PR в репозиторий sample-app, которая была направлена на использование новой улучшенной библиотеки paypal-scripts, и на переход с .js-файлов на .ts и .tsx-файлы. Потом были праздники, а потом мой PR был одобрен. Как результат, теперь в каждом новом проекте в PayPal используется статическая TypeScript-типизация.

Конечно, после того, как некто создаёт новый проект, он может делать с ним всё, что ему захочется. Скажем, может удалить весь шаблонный код и писать его на Elm, или на чём угодно другом. Это совершенно нормально. Но авторы большинства проектов придерживаются тех технологий, которые были использованы при их создании благодаря так называемому «эффекту умолчания [6]».

Почему я так долго шёл к TypeScript?

Вопрос, вынесенный в заголовок этого раздела, часто задавали мне фанаты TypeScript. Дело в том, что я уже давно знаком с TypeScript, но отношения у меня с этим языком до некоторых пор не складывались. Так, я помню, как примерно в 2013 году коллега предложил мне перевести код объёмом примерно в 500 тысяч строк на TypeScript. Тогда я это предложение отверг, но не особенно жалею об этом, так как в те времена TS был достаточно молодым языком. А однажды [7] я даже брал интервью у Андерса Хейлсберга [8], создателя TypeScript.

Вот из-за чего я всё это время держался в стороне от TypeScript.

▍Причина №1. Боязнь разрушить сложившуюся рабочую среду, основанную на Babel и ESLint

Для меня, очень долго, главнейшим плюсом Flow перед TypeScript было то, что Flow лучше сочетался с инструментами, к которым я привык. В частности, я уже многие годы с удовольствием пользуюсь Babel и ESLint, мне нравится писать собственные плагины и для того, и для другого (вы тоже, кстати, можете этому научиться [9]). Мне нравилось то, что вокруг Babel и ESLint сложились огромные сообщества. В результате отказываться от них я категорически не хотел. Собственно говоря, продолжалось это вплоть до недавних событий, так как, если бы я собрался с головой уйти в TypeScript, мне пришлось бы оставить и то и другое. Конечно, в мире TypeScript есть такая штука как TSLint, но сообщество ESLint значительно больше.

Во Flow же мне особенно нравится то, что для того, чтобы включить его в свой рабочий процесс, нужно выполнить лишь несколько простых действий:

  1. Надо подключить к Babel пресет с поддержкой соответствующего синтаксиса.
  2. Нужно добавить в начало каждого файла, проверку типов в котором требуется организовать, конструкцию // @flow (существует плагин [10] для ESLint, который позволяет это проверить).
  3. Добавить в проект скрипт, позволяющий запустить Flow для проверки типов в кодовой базе.

Мне очень нравится то, что проверка типов (с помощью Flow) и сборка проектов (средствами Babel, Webpack или Rollup) разделены. Мне не хотелось связывать свою жизнь с TypeScript, в частности, из-за того, что его компилятор, в любом случае, не понимал бы плагинов для Babel моей собственной разработки. А ещё — из-за того, что у меня был Flow — вполне сносный инструмент.

Теперь же всё продолжает работать как обычно. Благодаря Babel 7 (в частности, речь идёт о @babel/preset-typescript [11]) можно сохранить привычные инструменты и, кроме того, получить в своё распоряжение большинство возможностей TypeScript. Главная проблема — это сделать так, чтобы инструменты принимали бы файлы с расширениями .ts и .tsx, но, к счастью, эта проблема решаема.

▍Причина №2. Контрибуторам придётся учить TypeScript для того, чтобы внести вклад в проект

Я говорю, в основном, об опенсорсе, но необходимость освоения TypeScript теми, кто хочет вносить вклад в проекты, относится и к тому, чем я занимаюсь на работе. При этом я всегда считал, что рабочие проекты должны быть типизированными, и достигалось это средствами Flow. Я старался не пользоваться Flow в моих опенсорсных проектах, потому что тем, кто решил бы к ним присоединиться, пришлось бы осваивать Flow. Я сам всегда об этом говорил, но, подсознательно, всегда приводил контраргумент, который заключается в том, что типизация — это, по своей сути, лишь ещё одна форма тестирования, а тем, кто хочет вносить вклад в опенсорс, всё равно, приходится разбираться с тестированием.

Честно говоря, отказ от использования некоей технологии в опенсорсе только из-за того, что потенциальный контрибутор может ей не владеть, кажется мне плохим оправданием отказа от этой технологии. И, по мере того, как всё больше и больше программистов осваивают TypeScript, я думаю, что, возможно, через некоторое время буду писать на TS и свои опенсорсные проекты.

▍Причина №3. Мощная система вывода типов Flow

Я читал этот [12] пост, и он мне очень понравился. В особенности его последняя строка, в соответствии с которой при использовании Flow типы добавляют для того, чтобы сделать сообщения об ошибках приятнее, а не для того, чтобы их выявлять.

Так оно и есть. В наши дни Flow имеет более мощную систему вывода типов, чем TypeScript, и это меня обнадёживало.

▍Причина №4. Flow, как и React, родом из Facebook

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

▍Причина №5. Фанатичные приверженцы TypeScript

Думаю, все знают, что если некто по-настоящему восхищён некоей технологией, то он, не замолкая, всем вокруг о ней рассказывает. Тут кто-нибудь пользуется vim [13]? И приверженцы TypeScript — не исключение.

В сообществе TypeScript, кстати, полно замечательных людей. Добрых, готовых прийти на помощь, полных энтузиазма, дружелюбных. Но мне приходилось пересекаться и с такими любителями TS, которые назовут человека дураком только из-за того, что он не пользуется TypeScript, или не понимает его, или пользуется чем-то другим. Они демонстрируют отсутствие способности к пониманию собеседника, а их позиция отдаёт снобизмом. Это — не то сообщество, частью которого я хотел бы стать. Я имею в виду то, что воодушевление, вызываемое выбранной кем-то технологией — это замечательно, но если оно заходит настолько далеко, что фанат этой технологии начинает притеснять тех, кто выбрал что-то другое, это уже весьма печально [14].

У меня всё ещё остаются некоторые опасения по этому поводу. Но я надеюсь, что все вместе мы сделаем так, что сообщество TypeScript будет более позитивным.

Теперь, когда я рассказал о причинах, по которым не спешил переходить на TypeScript, расскажу о том, что меня не устраивает во Flow.

Проблемы Flow

Как я уже говорил, в определённый момент я очень устал от Flow. Вот один из твитов [15], в котором я делился одной из главных проблем, с которой столкнулся при работе с Flow. Заключалась она в том, что для того, чтобы Flow заработал, регулярно приходится, после его неудачного запуска, его останавливать, а потом запускать снова. Вот ещё один мой твит [16], где речь идёт о неправильной работе Flow.

Меня окончательно оттолкнули от Flow регулярно возникающие проблемы с его надёжностью. Плагины для редакторов работали, так сказать, с переменным успехом (должен признаться, что я не работал с Nuclide, и возможно, попробуй я его, моя жизнь сложилась бы иначе, но я пробовал работать с Flow в Atom и в VSCode), я постоянно сталкивался с какими-то странностями. Это было весьма досадно, так как подрывало мою веру в используемую мной систему контроля типов.

Когда я, в ноябре, увидел этот [17] твит, он выразил то, о чём я уже размышлял; краткий рассказ о переходе с Flow на TypeScript совпал с моим видением ситуации. Я, честно говоря, не мог перестать думать о том, чтобы как следует взяться за TypeScript. В итоге я так и поступил и я очень этому рад.

Вопросы и ответы

▍Почему вы не пользуетесь TSLint?

На самом деле, я реализовал поддержку TSLint [18] в paypal-script. Это был один из первых скриптов, который у меня заработал. Я собирался принимать решение о том, использовать ли TSLint или ESLint, основываясь на том, есть ли в проекте файл tsconfig.json. Но потом я вспомнил, что у нас есть некоторые ESLint-плагины собственной разработки (например, для проверки интернационализации), на переписывание которых в виде плагинов для TSLint мне не хотелось тратить время. Кроме того, интерфейс командной строки TSLint обладает меньшими возможностями, чем у ESLint, и он не очень хорошо подходил для совместной работы с paypal-scripts. Возможно, через некоторое время я снова присмотрюсь к TSLint.

Да, хочется отметить, что сообщество ESLint всё ещё гораздо больше, чем сообщество TSLint. Кроме того, я постепенно понимаю, что хорошая система контроля типов делает плагины для линтинга бесполезными. Пока же я использую с TypeScript ESLint, и то, что получается, выглядит совсем неплохо. Вот [19] моё видео на эту тему.

И, кстати, у меня такое ощущение, что команда TypeScript склоняется в сторону ESLint, поэтому я полагаю, что я сделал правильный выбор.

▍Почему вы не выбрали Reason?

Я, в переписке под этим [15] твитом, ответил на предложение попробовать TypeScript, сказав, что уж лучше перейду с Flow на ReasonML. На самом деле, я часто говорил о переходе на Reason [20] до перехода на TypeScript. Одной из главных причин подобных утверждений было мое желание сохранить привычные инструменты, о котором я уже рассказывал. Но, так как ни от чего отказываться мне не пришлось, TypeScript оказался для меня более привлекательным. Мне и сейчас очень нравится Reason, но переход на Reason означал бы необходимость огромных изменений для многих сотрудников PayPal. И хотя я думаю, что они с этим справились бы, я полагаю, что им комфортнее будет пользоваться TypeScript, чем пытаться изучать новый язык.

Вероятно, если бы я выбрал Reason, мой PR никогда не попал бы в репозиторий sample-app. Одно дело — подвигнуть коллег на то, чтобы пользоваться, в сущности, тем, что можно назвать «типизированным JavaScript» (особенно если с их стороны не требуется поддержка неких конфигураций), и совсем другой разговор состоится в том случае, если попытаться призвать коллег использовать совершенно другой язык и совершенно другую экосистему (и тут совершенно неважно то, насколько хорошо этот язык взаимодействует с JS и npm).

Итоги

Сейчас мне хотелось бы поблагодарить [21] всех пользователей Твиттера, под влиянием которых сформировалось моё видение TypeScript. Как я уже говорил, то, что библиотека paypal-scripts попала в репозиторий sample-app в PayPal, возможно, главное достижение моей карьеры. И я считаю, что то, что теперь шаблоны всех новых приложений в компании по умолчанию оснащаются поддержкой TypeScript — это огромный плюс для всех сотрудников PayPal. Я безмерно рад тому, что выбрал TypeScript.

Уважаемые читатели! Как вы думаете, стоит ли тем, кто пользуется Flow, смотреть в сторону TypeScript?

Почему в основе каждого нового веб-приложения в PayPal лежит TypeScript? - 2 [22]

Автор: ru_vds

Источник [23]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/306907

Ссылки в тексте:

[1] материал: https://habr.com/ru/company/ruvds/blog/437464/

[2] Image: https://habr.com/ru/company/ruvds/blog/437986/

[3] уже писал: https://blog.kentcdodds.com/automation-without-config-412ab5e47229

[4] Flow: https://flow.org/

[5] коллеге: https://twitter.com/xjamundx

[6] эффекту умолчания: https://en.wikipedia.org/wiki/Default_effect

[7] однажды: https://javascriptair.com/episodes/2016-08-31/

[8] Андерса Хейлсберга: https://twitter.com/ahejlsberg

[9] научиться: https://frontendmasters.com/courses/linting-asts/

[10] плагин: https://github.com/gajus/eslint-plugin-flowtype/tree/ae28b639670284956d32bdcacc4b9d53f7cd3c12#eslint-plugin-flowtype-rules-no-types-missing-file-annotation

[11] @babel/preset-typescript: https://babeljs.io/docs/en/babel-preset-typescript

[12] этот: https://jamie.build/adopting-flow-and-typescript.html

[13] vim: https://twitter.com/iamdevloper/status/676695839524282368

[14] весьма печально: https://twitter.com/kentcdodds/status/1081569132573646848

[15] твитов: https://twitter.com/kentcdodds/status/997571730536321025

[16] твит: https://twitter.com/kentcdodds/status/1019704559692894209

[17] этот: https://twitter.com/jamiebuilds/status/1064649666275340288

[18] TSLint: https://palantir.github.io/tslint/

[19] Вот: https://www.youtube.com/watch?v=Pl2heYVwQ-Q&list=PLV5CVI1eNcJgCrPH_e6d57KRUTiDZgs0u

[20] Reason: https://reasonml.github.io/

[21] поблагодарить: https://twitter.com/kentcdodds/status/1081598314934460416

[22] Image: https://ruvds.com/ru-rub/#order

[23] Источник: https://habr.com/ru/post/437986/?utm_source=habrahabr&utm_medium=rss&utm_campaign=437986