Устарел ли next-intl? И как реально оптимизировать такую архитектуру

от автора

Когда Next.js перешел с Pages Router на App Router и убрал встроенную поддержку i18n-роутинга, библиотека next-intl стала стандартом по умолчанию для большинства команд. Ян Аманн проделал отличную работу по ее поддержке, и долгое время это был самый надежный выбор для мультиязычных проектов.

is next-intl outdated

is next-intl outdated

Я давно занимаюсь профилированием производительности интернационализированных приложений на Next.js. За последние годы вся React-экосистема заметно сместилась в сторону серверных компонентов (RSC) и оптимизаций на этапе компиляции. Но если заглянуть под капот того, что next-intl реально отдает в браузер на проде, становятся видны явные архитектурные узкие места.

Главная проблема даже не в весе самого рантайма (хотя провайдер и парсер ICU отъедают около 12 КБ gzipped еще до показа первого слова). Главная беда — это утечка переводов между страницами.

В подавляющем большинстве проектов NextIntlClientProvider подключается в корневом лейауте вместе с getMessages(). В итоге пользователь открывает обычную страницу /contact, а браузер послушно выкачивает тексты для /dashboard, /pricing, настроек и вообще всего приложения. В нашем тесте на стандартном проекте из 10 страниц около 90% веса переводов, пришедших на конкретный роут, относились к совершенно другим экранам.

Кроме того, вызов t("key") динамически вычисляет строку во время выполнения. Из-за этого ни Webpack, ни Turbopack не могут понять, какие именно ключи используются, и не могут вырезать лишние строки через Tree-shaking.

Отдельная боль — костыли вокруг серверных компонентов (RSC). Чтобы заставить работать статическую генерацию (SSG) в App Router, разработчикам next-intl пришлось внедрить заплатку setRequestLocale(locale) (ранее unstable_setRequestLocale). Ее приходится вручную прописывать в самом начале каждого лейаута, подлейаута и страницы. Забудете хоть в одном месте — Next.js молча откажется от статики и переключит роут на динамический рендеринг при каждом запросе. Хуже того, в клиентских компонентах и переиспользуемых дизайн-системах нет нормального синхронного способа получить перевод: приходится либо оборачивать всё в контекст-провайдеры, либо вручную пробрасывать locale пропсами через все слои дерева компонентов (prop-drilling).

## Как оптимизировать такое решение?

Если вы уже используете next-intl на проде, есть несколько рабочих шагов, чтобы привести бандл в порядок.

Во-первых, откажитесь от загрузки всех переводов в корневом лейауте. Разбейте JSON-файлы на неймспейсы по конкретным роутам и вызывайте getMessages() локально на уровне страниц или вложенных лейаутов. Да, ручной маппинг страниц и неймспейсов требует дисциплины, чтобы случайно не потерять ключ, но это сразу убирает тонны чужого текста из чанков.

Во-вторых, выносите переводы в React Server Components везде, где это возможно. Если отрисовывать статичный текст через getTranslations() на сервере, а не через useTranslations() в клиентских компонентах, строки уходят в браузер в виде чистого HTML. Это дает ноль оверхеда на рантайм и ноль лишней нагрузки на гидратацию.

В-третьих, стоит присмотреться к статической экстракции на этапе сборки. Современный i18n постепенно уходит от передачи сырых JSON-словарей клиенту. Решения вроде Intlayer анализируют импорты компонентов при сборке, автоматически отсекают неиспользуемые ключи для каждого роута и избавляют от ручной возни с неймспейсами, костылей вроде setRequestLocale и проброса пропсов в дизайн-системах. Для существующих кодовых баз есть слой совместимости @intlayer/next-intl, который подменяет алиасы и дает тришейкинг на уровне компилятора без необходимости переписывать вызовы useTranslations.

Если у вас крутится мультиязычный Next.js на проде, откройте Network во вкладке разработчика и проверьте, сколько неиспользуемого текста улетает пользователю на первом экране. Там часто скрываются очень легкие победы по оптимизации.

Подробные замеры, методологию бенчмарков и цифры можно посмотреть в полной статье:

https://intlayer.org/ru/blog/is-next-intl-outdated

ссылка на оригинал статьи https://habr.com/ru/articles/1077908/