Дисклеймер: Эта статья — честный опыт редизайна, со всеми шишками и временными костылями. Мы не призываем повторять все решения (особенно про прямой доступ к БД). Это не best practices, а живой дневник инженерной команды, которая решала задачи в условиях ограниченных ресурсов.
Вступление
Вернувшись из путешествия, очень хочется рассказать о нём друзьям и знакомым. Особенно если поездка выдалась интересной и непредсказуемой.
Этот проект напомнил мне путешествие: непредсказуемый, интересный, местами опасный. Расскажу, как мы переписывали сайт с Perl на Nextjs, что выбирали и какие приключения нас ждали.
Почему решили переписать сайт
В основе старого сайта лежат следующие технологии: Perl и jQuery. Почему мы не захотели оставаться на них и решили рядом писать на новом стеке?
- В команде есть фронты со знанием React. В соседних отделах так же основной стек — React.
- Найти разработчиков под старый стек — задача не из лёгких.
- Хочется чего-то стильного, модного, молодёжного (СММ), чтобы щеголять современным стеком среди коллег.
- Чисто человеческая причина: никакой редактор кода не умеет работать с нашим почти самописным шаблонизатором. А подсветка кода — это уже даже не базовый минимум для разработчика.
Стек и как мы его выбирали
Выбирая стек, мы руководствовались причинами из прошлого пункта. Взгляд почти сразу пал на Nextjs. На нём буквально свет клином сошёлся. Даже уже не вспомню других претендентов — мы их быстро отмели. Как натура романтическая, не могу воздержаться от аналогий: вокруг много хорошего, но ОН такой один.
Даже обсуждали делать сайт на каком-нибудь питонячем фреймворке. Но всё упирается в вопрос: «Можно. А зачем?» Плохо написать можно на любом стеке. А учитывая, что для большинства из нашей команды Python «не родной», мы снова и снова возвращались к Nextjs.
Минусы Nextjs
- Не оптимальный бандл, если код состоит всего из Hello World. Но наш сайт всё-таки сложнее.
- Уязвимости, о которых мы знали с самого начала (об этом позднее).
- Технология находится под пристальным вниманием, и все, кто хочет её взломать, обязательно постараются это сделать.
Плюсы Nextjs
- СММ <3
- Мы умеем работать с JSX и React, а значит, порог входа в Nextjs будет не таким высоким.
- Огромное сообщество. Некоторые проблемы, которые не удавалось решить «своим умом», выносились на обсуждение туда. Спасибо ему большое!
- На этом фреймворке написано огромное количество сайтов. Можно быть уверенными, что в случае ошибок со стороны разработчиков фреймворка исправления не заставят себя ждать.
- Пункт 3 из списка минусов — это тоже преимущество! Если где-то найдена проблема, её обязательно исправят.
Docker
Кроме Nextjs у нас есть Docker. Мы собираем образ, кладём его в наш регистр, раскатываем контейнер на три стенда. Почему три? Два продовых и одна версия для тестирования сайта на окружении прода.
Какую ещё пользу принесла докеризация? Мы раскатываем стенд под каждую задачу: создаём образ с нужной версией, запускаем контейнер на порту, пишем nginx-конфиг, который смотрит куда надо.
Проблемы
Уязвимости
Однажды утром (которое я запомню надолго) неизвестная группа исследователей безопасности выпустила скрипт, позволяющий взломать машину, на которой крутится сайт. Вся работа для взлома сводилась к тому, что можно было склонировать репозиторий и запустить скрипт, передав адрес сайта. Вуаля. Вы хакер, возьмите с полки пирожок.
И слава сообществу — разработчик оперативно выкатил патч, и уже через пару часов мы его подхватили и закрыли лазейку.
Как параллельно разрабатывали два сайта на принципиально разных технологиях
Мы решили положить два сайта рядом и определять, какую версию показывать, с помощью nginx. И вроде всё хорошо. Какие трудности могли возникнуть?
Nextjs на клиенте использует свой роутинг. При навигации он перехватывает клик, предотвращает перезагрузку страницы, подгружает только необходимые скрипты и динамически обновляет контент с помощью React.
А что происходит, если страницы нет в новом приложении? Запрос не уходит дальше, показывается 404-я страница.
Чтобы всё работало как надо — для нового сайта модный роутинг, для старого обычный — мы написали небольшой компонент-обёртку над ссылками. В нём хранили список мигрированных страниц и проверяли: если страница мигрировала — отдаём ссылку от Nextjs, если нет — рисуем ссылку с помощью привычного всем <a />.
Работа с данными
У нас не было ресурсов для написания полноценного API. Пока что мы решили это с помощью функций, которые ходят напрямую в базу. Теперь наши фронты могут не только красивенькие странички делать, но и написать селектик в базу.
Важное уточнение: это временное и вынужденное решение. Мы ограничили доступ к БД read-only пользователем и не даём фронту писать данные напрямую. Полноценное API в планах, но ресурсы пока там.
Но отсюда вылезла неочевидная проблема. Товарищ фронтендер (я), которого заставили писать сайт с серверным рендерингом, не думает о глобальном потеплении, вызванном работой серверов. Также он не думает о типах и о проверке их перед тем, как всунуть клиентские данные в запрос.
Из-за этого мы в какой-то момент стали тонуть в ошибках от PostgreSQL. Хорошо хоть используемая библиотека для запросов по умолчанию экранирует параметры, что защищает от классических SQL-инъекций (но мы всё равно переписываем эти участки, когда доходят руки).
Nextjs очень прожорливый
С этой проблемой мы боремся на протяжении всего переезда, как только начали работать с данными. Чуть что сделал не правильно — CPU в потолок улетает. Но Node.js никогда не славился экономностью, так что к этому мы были готовы.
Спасибо команде инфры, что настроили необходимые мониторинги и логирование. Теперь мы в курсе инцидентов и можем быстро на них реагировать.
Кеширование запросов
Nextjs не умеет кешировать POST-запросы. Для нас это было неочевидно, пока страницы с такими запросами не начали периодически отдавать 500-ю ошибку. Решили просто: убрали revalidate для этих страниц — и проблема ушла.
Что бы мы сделали иначе
Оглядываясь назад, мы бы не верили, что Nextjs «из коробки» решит все проблемы с производительностью, надо с самой первой строки думать
Расставание
К сожалению, наши дорожки с этой компанией разошлись. Не буду говорить почему — это отдельная и невесёлая история. Но сам проект я вспоминаю с теплотой. Он дал мне опыт, которого ни на одном курсе не купишь: как выживать в легаси, договариваться с командой и не сломаться, когда всё идёт не по плану. За это спасибо.
Итоги
Путешествие подходит к концу. Мы получили не только современный сайт, но и синяки, пару седых волос и твёрдое знание: если фронтендер лезет в бэкенд — жди глобального потепления.
Опубликовано с любовью к живым инженерным историям. Комментарии приветствуются, особенно конструктивные.

