Большие фронтенд-проекты не рушатся из-за одной ошибки. Чаще всего их «убивают» мелкие, но системные ошибки в архитектуре, которые приводят к бесконечным поломкам. Давайте рассмотрим самые частые анти-паттерны, с которыми сталкиваются реальные команды.
ℹ️ «Глобальное всё»
Когда всё в проекте глобальное: стили, состояния, утилиты. Это создаёт цепочку зависимостей, и любая правка может привести к непредсказуемым поломкам.
Решение: строгое разделение на модули, использование неймспейсов и изоляция слоёв. Это поможет избежать нежелательных побочных эффектов и сделает код более предсказуемым.
ℹ️ «Компоненты-монолиты»
Когда в коде все компоненты отвечают за UI, бизнес-логику, запросы, валидацию и управление состоянием, это может привести к тому, что код станет сложным для тестирования, переиспользования и чтения.
Решение: Для улучшения структуры и поддерживаемости кода необходимо разделить его на слои: UI, управление состоянием, доменная логика и взаимодействие с API.
ℹ️ «Push-архитектура»
Каждый компонент тянет данные сам и вот тут начинается хаос: дублирование запросов, гонки условий, зависимости на каждом шагу.
Решение: централизованный слой данных. Используйте query-клиенты, сервисы или модели для эффективного управления данными.
ℹ️ «Секретные зависимости»
Компоненты, которые используют скрытые зависимости, такие как localStorage, window, сторонние сервисы или скрытые контексты, не указаны явно.
Решение: всегда документируйте зависимости и явно описывайте их в коде. Это упростит тестирование и переносимость компонентов.
ℹ️ «Тяжёлые re-render цепочки»
Когда один компонент меняет state, и пол-страницы перерисовывается, вызывая лаги и замедление интерфейса.
Решение: используйте signals, selectors и fine-grained реактивность. Архитектурная изоляция поможет минимизировать лишние ререндеры.
ℹ️ «Всё через Redux / Context / глобальный стор»
Когда вы храните глобальный стейт там, где он должен быть локальным. В итоге глобальное состояние становится тяжёлым и трудным для управления.
Решение: минимизируйте использование глобального стейта. Локальные состояния должны храниться локально.
ℹ️ «Типизация по настроению»
Когда часть кода типизирована, а часть — нет, или используется any. В итоге типизация не защищает, а мешает.
Решение: установите единые правила типизации и используйте строгий линтинг для соблюдения этих правил.
ℹ️ «Сложность вместо простоты»
Когда для решения простых задач используются сложные абстракции, кастомные DI, самописные хуки и роутеры, что усложняет поддержку кода.
Решение: используйте стандартные подходы и решения, не усложняйте систему без нужды. Простейшие функции могут быть более чем достаточны.
ℹ️ «Отсутствие архитектурных границ»
Когда компоненты могут импортировать что угодно и откуда угодно, проект превращается в клубок зависимостей, которые сложно отслеживать.
Решение: используйте feature-sliced или modular архитектуру, следите за слоями, внедрите статический анализ зависимостей и запретите пересечения между слоями.
📌 Большие проекты не рушатся на раз-два. Они как бы потихоньку «гниют», но если у вас хорошая архитектура, дисциплина и вы регулярно что-то улучшаете, то можно избежать многих проблем.
🚪 Frontender's notes
