Здравствуйте, меня зовут Александр Черников. Я руковожу разработкой UI проекта “Цифровой корпоративный банк” — обновлённой версии Сбербанк Бизнес Онлайн, интернет-банка для юридических лиц. Мы разрабатываем stand-alone клиент, мобильное приложение и, собственно, web-клиент, о котором и пойдёт речь. В своих статьях я буду делиться ценным опытом нашей команды, а конкретно в этом посте опишу наш технологический стек и остановлюсь на том, почему мы выбрали Typescript в качестве основного языка.
Новую версию Сбербанк Бизнес Онлайн мы пишем 2,5 года. Уже в следующем году мы планируем перевести на него всех корпоративных клиентов Сбербанка.
Итак, начнем со стека. Мы внедрили TypeScript, React, Reflux(legacy), Redux, Bluebird Promise и Bootstrap. Стили пишем на LESS. Все это добро мы собираем с помощью Babel, Webpack и его плагинов. Webpack пока первой версии, но собираемся перейти на вторую. Многие могут спросить: зачем нам Typescript и Babel одновременно? Во-первых, раньше TypeScript не все умел транспилировать, и только недавно сравнялся с Babel по этой функциональность. Во-вторых, TypeScript не умеет кэшировать. А babel умеет хранить готовые ES5 скрипты в папке. Если исходники не поменялись, он сразу берет их оттуда. Когда проект собирается несколько минут, такая экономия времени очень радует.
Стек технологий достаточно свежий. Ребятам приходится вникать сразу в несколько вещей: например, в TS, React, Redux, в сам проект и в термины нашего банка. Из 50-60 человек только 20 процентов работают в штате, остальные подключаются от вендоров и часто меняются.
Как мы справляемся в таких условиях с code-review? Раньше несколько самых опытных разработчиков смотрели код всех команд, была такая небольшая пирамида. Сейчас мы стараемся равномерно распределить по командам. Во многих командах появились так называемые эксперты (хорошо разбираются в проекте, знают, что и где лежит), чтобы не изобретали велосипеды и прочее. Соответственно они review’ят не только ребят из своей команды, но и из других.
Review у нас немного автоматизировано и на pull-request у нас добавляются лейблы, которым нужно соответствовать. Тогда они станут зелеными и ПР автоматически сольется. Лейблы есть разные: Code-style, Expert, Architect, CSS, E2E-test и другие. Если меняются .less файлы — добавляется CSS, если меняется какой-то код ядра или низкоуровневых вещей — добавляется Architect. Чтобы получить Expert, нужно набрать как минимум 2 аппрува экспертов.
И если человек новенький на проекте или не очень силен в JS, тогда его код будет сильно отличаться от того, что было до code-review.
TypeScript и JavaScript
Я застал тот момент, когда многие писали на TS и использовали новые фичи, которые транспилируются в ES5. Но даже тогда мы использовали TS для типизации, для некоего статического анализа кода на ошибки. Да, на JS можно написать код грамотно и правильно, но он тебя не подстрахует так, как TS. Кто-то ставит в минусы, что приходится много писать TS-кода (overhead), т.е. типизация, типы, интерфейсы и др. Когда мы рефакторили “старый” код JS > TS, то выявлялись элементарные ошибки, которые сработают только в runtime. То запятая не там стоит, то точку забыли, то скобки рано закрыли и т.д., не говоря уже про недосягаемый код и неиспользуемые аргументы и пр… Когда система большая и команда не может покрыть всю систему тестами, то TS спасает. При 3000-4000 скриптов вообще трудно представить, как жить без TS.
Конечно, когда мы пишем код на JavaScript, то можем помочь компилятору и писать код, словно у нас типизированный язык: не переопределять переменные, не записывать в них разные типы, возвращать всегда один и тот же тип. Возникает вопрос: если при этом использовать babel.js, есть ли в таком случае смысл в изучении TypeScript?
Мы часто спорим по этому поводу. Некоторые коллеги говорят: “А зачем нам TS? Мы пишем код грамотно и проводим тщательно code-review, отбираем людей на собеседовании, да и вообще джедаи JS”. Но ведь человеческие факторы никто не отменял: лень, торопливость, невнимательность. Ничего не мешает подключить TS к вашему JS-коду. Если у вас действительно нет ни одной ошибки, то компилятор ничего не найдет — можете радоваться тому, что у вас отличная команда, и звезды сложились как надо. Но перестраховаться с помощью TS все равно не мешает. Тем более, что и особых затрат это не потребует.
К тому же, в этом году в версии 1.8 в TS сделали удобную фичу. Теперь можно проверить типы в чистом JS — достаточно добавить файлы “.js” в проект и allowJs флаг. Если есть какой-то код, который не хотите проверять, то спокойно его можно игнорировать через аннотацию @ts-nocheck. Во время code-review мелкие баги отловить почти нереально, а TS помогает экономить силы и время. А не то подольешь релизную ветку в develop с конфликтами в 100 файлов… хотел бы я посмотреть, как человек хладнокровно нажмет кнопку MERGE.
TypeScript vs Flow
“А как насчет Flow?” — спросите вы. Мы выбирали между ES6 и Typescript, про Flow тогда никто не знал. Для тех кому интересно, в чем разница их статического анализа кода, могу посоветовать интересный доклад Ильи Климова с конференции HolyJS 2017 Piter, где он сравнивает TypeScript и Flow.
Ложки дегтя
Помимо overhead у Typescript есть еще несколько недостатков:
- Существенное замедление сборки проекта. Но это, опять же, исключительно в нашей специфике сборки: Webpack + TS + Babel. У кого такая же конфигурация (+- babel), могу посоветовать использовать загрузчик ts-loader обязательно с флагом transpileOnly, а TSC запускать параллельно. А в режиме инкрементальной сборки (--watch), держать 2 процесса отдельно: webpack --watch и tsc --watch.
- Возникают проблемы с OutOfMemory ошибками nodeJS, особенно неприятные такие сюрпризы, когда нужно собрать проект и выпустить релиз через 3-4 дня, а быстро решить их не получается.
- Необходимость актуализации версий .d.ts для внешних библиотек. Слава Богу, закончилась пора с tsd > typings. И теперь все можно качать сразу через npm > @types. А что если вышла новая версия библиотеки, lodash например, а .d.ts еще нету? Тогда приходится выбирать: дописать самому (в репозиторий или выложить ПР на github в репозиторий DefinitelyTyped) или пока не использовать эту фичу.
- Поиск разработчиков с опытом на TypeScript. Это отдельные слезы нашего HR. Насколько мне известно, на рынке у всех сейчас проблема с поиском “продвинутых” frontend-разработчиков, с опытом написания серьезных SPA, Angular | React | Vue, Typescript, Redux и пр.
Автор: Sberbank