Когда я принял управление командой, её участники находились на 8-м месяце реализации 3-месячного проекта по перезапуску коммерческого сайта компании. Спустя два месяца ведения этой команды, я решил отказаться от всего достигнутого и начать сначала. Это история о том, почему я это сделал, как, и что в итоге получилось.

Перезапуск нашего сайта преследовал одну цель: обеспечить быструю отрисовку на стороне сервера.

В удачное время размер нашего JS-бандла составлял 168 МБ. На топовом MacBook Pro среде разработки для начала реагирования требовалось 3 минуты. Приходя на работу, инженеры уже по привычке вводили npm run dev и шли пить кофе, пока кулеры их компьютеров изо всех сил пыхтели, справляясь с нагрузкой, возложенной на них нашим раздутым проектом.

Где же всё пошло не так?

▍ Предыстория


Первым сайтом компании было одностраничное приложение на AngularJS. AngularJS не поддерживал отрисовку на стороне сервера (SSR, server-side rendering), поэтому первая загрузка страницы происходила медленно, и только потом уже всё начинало работать быстро.

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

Команда подумывала об использовании Angular 2, и хотя этот фреймворк значительно отличался от AngularJS, он казался логической основой для нового сайта. Мы даже следили за экспериментальной веткой разработки этим проектом функциональности SSR. Естественно, к моменту готовности сайта она тоже должна была быть готова.

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

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

Команда Angular двигалась к завершению функциональности SSR, и мы привносили последние штрихи в критические маршруты пользователей. Всё шло если не отлично, то по крайней мере… шло. Пока не встало.

У нас был рабочий сайт. Единственное, чего не хватало – это полноценной поддержки SSR. SSR работала, но без tree-shaking, а AOT-компилятор (критический этап в сборочном конвейере Angular) выдавал пакеты очень большого размера.

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

В итоге приятных бонусов для добавления не осталось, и мы две недели потратили на копание в SSR-ветке команды Angular, но раскидистая, незнакомая база кода и непоправимые ошибки всё сильно затрудняли. Поскольку проект был экспериментальным, толковой документации к нему не было.

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

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

У нас не было чёткого понимания, как мы сможем выпустить имевшийся у нас на тот момент продукт, и встал вопрос: «Можем ли мы позволить себе начать его с нуля?»

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

Если ситуацию не исправить, она неизбежно приведёт ко всё большей потере.

Я не спал ночами, обдумывая решения, которые привели к этому раскладу. По собственному опыту я знал, что React & Redux имели полноценную поддержку SSR.

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

Кроме того, эта мысль противоречила всем инстинктам, которые у меня были относительно масштабных переделок.

▍ Начинаем заново


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

  1. Что я буду продолжать следить за проектом Angular SSR, и в случае его выпуска мы тут же запустим сайт на Angular.
  2. Сайт на React будет доведён до работоспособного состояния за 6 недель, а через 10 мы его уже сможем запустить. Если мне это не удастся, то я пойду на понижение и найду себе замену.

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

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

Мне требовалось убедить команду использовать стек React, и единственным способом для этого была платформа DevEx. Они должны были увидеть, насколько продуктивно можно работать, если не опираться на их текущие отсталые инструменты.

Я набросал схему проекта React с SSR и выбрал для реализации один поток, установив амбициозную цель создать нашу домашнюю страницу – полностью отзывчивую и с поддержкой SSR – в течение дня моб программирования.

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

Все ценят быстрый цикл обратной связи. Даже короткое ожидание результата изменений может загубить весь рабочий поток.

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

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

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

▍ Развёртывание


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

Angular Universal с первоклассной поддержкой SSR в итоге был добавлен в Angular v5, вышедший в апреле 2018 года, где-то через шесть месяцев после завершения нашего сайта.

В этом проекте было нарушено два фундаментальных правила управления программными проектами:

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

Версия сайта на Angular как раз создавалась на экспериментальной, неподтверждённой технологии и до сих пор находится в активной разработке.

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

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

2. Не идите на масштабное переписывание проектов

Решение переписать сайт на Angular 2 без требования следовать поэтапным релизам завело команду в ловушку, вынудив создавать весь сайт до столкновения с основным риском.

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

Здесь внимательный читатель может сказать: «Подождите-ка. Разве проект на React не стал масштабным переписыванием?»

Отвечу так: «Изучайте правила, чтобы знать, когда их можно нарушать».

Я пошёл на сознательное нарушение этого правила, чтобы сохранить мораль команды.

В этом случае я сделал ставку на то, что передовой проект на React сможет сохранить в её участниках мотивацию. Втискивание React в легаси-проект на AngularJS не привело бы к достижению цели, а возвращение к старому коду после нескольких месяцев создания нового нанесло бы сильный удар по духу команды.

Это было очень ситуативное решение. Если бы мы не переходили с провального проекта на Angular 2, то я бы с самого первого дня пошёл на использование одной из прослоек совместимости между React и AngularJS, чтобы перенести сайт постепенно.

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

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

Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх ????️

Комментарии (22)


  1. DarthVictor
    03.09.2023 11:34
    +31

    Попробуйте в следующий раз DeepL вместо Google Translate

    Например в качестве перевода для

    We had a working website. The only feature missing was full SSR support. Server-Side Rendering worked, but not with tree-shaking, and the AOT compiler (a critical step in the Angular build pipeline,) was spitting out enormous bundle sizes.

    вместо

    У нас был рабочий сайт. Единственное, чего не хватало – это полноценной поддержки SSR. Отрисовка на сервере работала, но не при встряхивании дерева, а AOT-компилятор (критический этап в сборочном конвейере Angular) выдавал бандлы невероятного размера.

    он выдаёт

    У нас был работающий сайт. Единственное, чего не хватало, - полной поддержки SSR. Server-Side Rendering работал, но не с tree-shaking, а компилятор AOT (критический шаг в конвейере сборки Angular) выдавал пакеты огромных размеров.


    1. kogemrka
      03.09.2023 11:34

      Все переводы всё равно по правилам же снабжаются ссылкой на оригинал текста, верно?

      Напрашивается фичреквест для хабра.

      В статье-переводе добавить опцию по клику на абзац посмотреть перевод абзаца от глупой нейросетки и проголосовать на выбрасывание перевода от умного человека и замену на перевод от глупой нейросетки)


  1. zubrbonasus
    03.09.2023 11:34
    +26

    Каефно когда есть 10 месяцев времени и достаточно финансирование, чтобы сделать 2х месячный сайт. Мечта любого аутсорса )))


    1. Hardcoin
      03.09.2023 11:34

      Предположим, что времени нет. Это точно так же означало бы остановку проекта и выкидывание результатов. Но если руководству результат всё ещё нужен, то проект будут продолжать делать.


      1. zubrbonasus
        03.09.2023 11:34
        +1

        Если результата нет - нужны изменения в команде, или усилить или обновить. Топтаться на месте создавая что-то нерабочие - то ещё удовольствие.


        1. Hardcoin
          03.09.2023 11:34
          +5

          Именно это в статье и произошло, хоть и с опозданием.


        1. odilovoybek
          03.09.2023 11:34

          Замена команды - очень плохая идея, ссылки не могу кинуть на статьи с такими примерами, но читал об этом много раз. Нужно менять подход команды к проекту и/или менять рук. команды или добавлять новых понижая ставки старых разрабов (на "короткое время").


        1. zuek
          03.09.2023 11:34

          Было в моём прошлом несколько таких кактусов - от кастомной конфигурации 1С в 2022 году, тянущей свои корни из платформы 7.7 (это мой личный вывод, не как разработчика, а как "читателя" некоторых используемых обработок), до мобильного приложения и сайта, написанных на странном стеке, с применением React Native и MariaDB на бэке (и да, DBA, похоже, в разработке не принимал участия, и всё адово деградировало со временем).

          По моим наблюдениям, такое случается, когда бизнес хочет "по-быстрому проверить что-то новенькое", а потом этот прототип внедряют в критические бизнес-процессы.


  1. RemiZOffAlex
    03.09.2023 11:34
    +11

    У нас с собой было: огромный проект аля чёрный ящик; 10 месяцев реализации всего подряд в спагетти код; angularjs, 168МБ и никого, кто в этом мог бы разобраться; ни одной страницы внятной документации по проекту; убежавший прошлый руководитель проекта; куча потерянного времени; гора потерянных денег; React & Redux и выкидывание переиспользуемого кода, т.к. прошлая команда тоже делала его правилам, шаблонам, модулям, контрактам, GRASP, SOLID, DRY, KISS и т.д. и т.п.


    1. sergeaunt
      03.09.2023 11:34
      +23

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


      1. Boilerplate
        03.09.2023 11:34
        +18

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


        1. sergeaunt
          03.09.2023 11:34
          +4

          Мы вот ржем, а ведь это всё очень жизненно и грустно. Особенно "рано или поздно мы перейдем и на эту дрянь ради достижения лучших KPI", причем настоящей причиной будет "директор читал о ChatGPT в журнале авиакомпании во время полета".


          1. VADemon
            03.09.2023 11:34
            +1

            Примерно такие чувства вызывала статья про айтишный инструмент написанная с ЦА управленцев. Читать и смешно и противно.


  1. dom1n1k
    03.09.2023 11:34
    +17

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


  1. excoder
    03.09.2023 11:34
    +5

    Ооо, так это это в Радио-Т обсуждали намедни ????

    Ужасно осознавать, куда мы со всем этим прикатились.

    Уже со времени т.н. AJAX времён IE 5.0 можно было заподозрить неладную канву развития той области, что мы нынче знаем как Web Development.


  1. spidersarecute
    03.09.2023 11:34
    +5

    Не понимаю, зачем им понадобился SPA? Разве нельзя просто сделать обычный сайт по классической схеме, а для перехода между страницами без перезагрузки воткнуть библиотеку вроде https://github.com/defunkt/jquery-pjax ?

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


    1. Alexufo
      03.09.2023 11:34

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


  1. Cringeon
    03.09.2023 11:34
    +1

    Когда-нибудь они узнают, что можно развернуть SSR на ноде с puppeteer буквально за 1 день(но это не точно)


  1. copist
    03.09.2023 11:34

    Спорить не буду, тем более что это перевод и источник очень старый, ориентировочно 2016-2017 года [https://habr.com/ru/articles/341688/]

    Для общей эрудиции
    1 что угодно можно натворить на JS и пропустить через prerender.io
    2 теперь Angular Universal более чем хорош и, к примеру, onclass.com вполне индексируется ботами
    3 Vue давно SSRится довольно просто nuxt.com
    4 Метеор давно SSRится довольно просто meteor.com
    5 Aurelia давно SSRрится aurelia.io


  1. copist
    03.09.2023 11:34

    В комментариях к оригинальной статье:

    I don't understand the 'techo side' of the story Dan, but the leadership is key, well done mate.

    В технической части истории не вкурил, но лидерство имеет решающее значение, молочага.


    1. Samhuawei
      03.09.2023 11:34

      Да и лидерство такое себе - взять в руку пистолет и ура в атаку, не представляя себе последствий (если что расстреляйте меня). Представляю себя на месте владельцев бизнеса. Сначала один бородач впарил Angular, потом пришёл второй и впарил React. Ну да, повезло, но наверняка осадочек остался и больше в АйТи они играть не будут.


  1. Psychosynthesis
    03.09.2023 11:34

    В удачное время размер нашего JS-бандла составлял 168 МБ

    Я может чего-то не понимаю, но попахивает шизофренией какой-то.