Недавно вышел релиз Next.js 13,4, в котором App Router официально признан стабильным. App Router  —  это рабочее название новой парадигмы, в которой можно создавать приложения Next.js. Эта новая парадигма, ранее выпущенная как бета-версия в Next.js 13 под названием App Dir, представила целый ряд усовершенствований, которые привели сообщество в полный восторг.

Я стал одним из первых пользователей Next.js App Router и был восхищен оптимизированным процессом разработки и производительностью рендеринга.

Я точно буду использовать Next.js App Router в каждом сайд-проекте. Но возникает вопрос: готов ли этот инструмент, официально признанный стабильным, к крупномасштабному производственному проекту?


Особенности App Router

Прежде чем ответить на этот вопрос, рассмотрим особенности App Router, которыми он выгодно отличается от классического Next.js Pages Router.

React Server Components

Основным преимуществом App Router является использование новой архитектуры React Server Components.

Подобно тому, как React изменил представление о UI-разработке, React Server Components (RSC) представляет новую ментальную модель для создания гибридных приложений, использующих сервер и клиент.

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

Потоковая передача и Suspense

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

Приведенный выше код  —  пример применения серверного компонента, который использует React Suspense. Серверный компонент Posts первоначально отображает PostListSkeleton в качестве состояния загрузки. Обратите внимание, что компонент PostList является асинхронным. Как только промис разрешится, отрисованное содержимое компонента будет передано клиенту, заменив состояние загрузки.

Что здесь самое приятное? Больше не нужно получать данные на клиенте. Больше не нужно получать данные в useEffect. Больше никаких неинтуитивных библиотек с хуками для выборки данных. Все данные теперь извлекаются на сервере. Next.js даже использовал манкипатчинг Fetch, добавив функциональность кэширования для дедубликации запросов. Это позволяет получать данные непосредственно в компоненте, которому они нужны, используя нативный Fetch API.

Server Actions (Alpha-версия)

Server Actions  —  это решение для обработки мутаций на сервере, представленное в Next.js 13.4, которое можно вызывать непосредственно с клиента. Server Actions интегрируются с остальным жизненным циклом данных и могут изменять данные, ревалидировать любой существующий кэш этих данных, а затем повторно отображать страницу за один сетевой цикл.

Приведенный выше код показывает, насколько легко использовать Server Action. В данном случае имеется Server Action с именем saveContact. Определяем его как Server Action директивой use server. Затем устанавливаем действие формы на имя Server Action. Когда форма будет отправлена, она вызовет Server Action. Поскольку Server Action работает на сервере, можно использовать секретные данные или делать вызовы непосредственно к базе данных.

Вложенные Routes & Layouts

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

App Router улучшает предыдущую реализацию Page Router, включая новые возможности.

  • Layouts можно совместно использовать на нескольких страницах.
  • Route Groups позволяют упорядочивать маршруты без изменения URL, а также выбирать определенные маршруты в макете.
  • Loading UI помогает создавать значимые состояния загрузки.
  • Intercepting Routes позволяют загружать маршрут разными способами в зависимости от контекста.

Это далеко не все возможности. Чтобы узнать больше, рекомендую ознакомиться с официальной документацией.

Встроенная функция оптимизации SEO

Последняя функция, которую мы рассмотрим,  —  это новый API Metadata, который используется для улучшения SEO. Он включает все необходимые SEO-настройки, в том числе протокол Open Graph. Доступны два способа его использования: статический и динамический.

Пример статической реализации SEO
Пример динамической реализации SEO

Обратите внимание, что в приведенном выше примере getProduct вызывается несколько раз. Как уже отмечалось, Next.js способен к дедупликации запросов, поэтому API вызывается только один раз.


Готов Next.js App Router к производству?

Безусловно, мне нравится Next.js App Router, но готов ли он к производству крупномасштабных приложений? Чтобы выяснить это, я провел эксперимент, попытавшись рефакторизовать производственное приложение с Next.js Pages Router на App Router. Вот некоторые проблемы, с которыми я столкнулся.

Проблема с мокингом

Первая проблема, с которой я столкнулся, заключалась в том, чтобы заставить мокинг работать. Я придерживаюсь философии тестирования Кента Доддса:

Пишите тесты. Не слишком много. В основном интеграционные.

Примечание: цитата на самом деле принадлежит генеральному директору Vercel Гильермо Рауху.

При написании интеграционных тестов необходимо решение для мокинга. В последнее время при фронтенд-тестировании стало популярным мокинг-решение MSW. Оно работает, перехватывая запросы с помощью работ сервисов и возвращая определенную вами полезную нагрузку мока. Оно делает это без необходимости запускать сервер-ноду, что значительно упрощает настройку тестирования и обеспечивает приятный опыт разработчику.

К сожалению, когда я попробовал использовать MSW с Next.js App Router, ничего не вышло. Я решил обратиться к Twitter, ожидая, что это распространенная проблема, у которой есть решение, но, к сожалению, это оказалось не так:

Мокинг-решение

К сожалению, для меня это стало проблемой, но если вы хотите использовать Next.js App Router, есть и другие варианты. В качестве альтернативы MSW можно попробовать одно из мокинг-решений, которое задействует сервер-ноду вместо перехвата. Другой вариант  —  использовать E2E-тестирование вместо интеграционного тестирования. Однако я бы не позволял новой фиче определять стратегию тестирования своего приложения.

Проблема с Emotion

При разработке любого крупного приложения я обязательно использую библиотеку компонентов, например Chakra, Mantine или MUI. Они обеспечивают необходимые функции доступности, которые требуются для масштабной работы. Эти и любые другие библиотеки компонентов на основе Emotion в настоящее время не поддерживают Server Components. При попытке использовать компонент из одной из этих библиотек в Server Component вы столкнетесь с ошибкой:

Вы импортируете компонент, которому нужен useRef. Он работает только в клиентском компоненте, но ни один из его родителей не помечен как “use client”, поэтому по умолчанию они являются серверными компонентами.

Корень этой проблемы  —  CSS-in-JS, который поставляется с @emotion/styled. CSS-in-JS  —  это то, что позволяет использовать функцию Style Props, которая в значительной степени способствует тому, что эти библиотеки компонентов становятся мощными инструментами.

Создатель Chakra недавно написал статью о будущем Chakra, где описывает эту проблему и работу, которую команда Chakra проводит для ее решения. Если вкратце, они работают над новым решением для стилизации под названием Panda, не зависящим от фреймворка. Оно позволит использовать CSS-in-JS с нулевым рантаймом путем извлечения стилей во время сборки. Однако это решение все еще находится на ранней стадии эксперимента.

Решение на основе Emotion

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

Одно из решений, которое я использую и которое меня еще не подводило,  —  это Tailwind CSS. Поскольку Tailwind использует решение с нулевым рантаймом, аналогичное тому, что создает команда Chakra, оно работает просто отлично. Однако Tailwind не обладает всеми преимуществами библиотеки компонентов. Он не включает функции доступности  —  это просто инструмент для стилизации, поэтому вместе с Tailwind вам понадобится библиотека компонентов на основе Tailwind, например Headless UI, Daisy UI или Radix UI.


Заключение

Итак, готов ли Next.js App Router для крупномасштабных производственных приложений? В случае с Udacity ответ отрицательный. В Udacity мы используем MSW и Chakra для приложений Next.js, и из-за отсутствия всесторонней поддержки для них пока не имеет смысла начинать использовать App Router.

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

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Kolby Sisk: What is Next.js App Router & Is it ready for the main stage?

Предыдущая статьяКак создать API-шлюз в Rust посредством библиотеки Hyper
Следующая статьяСамые полезные библиотеки Go