Как создавать микрофронтенды с использованием Multi-Zones и Next.js

Примеры

Multi-Zones — это подход к микрофронтендам, который разделяет большое приложение на домене на несколько меньших Next.js-приложений, каждое из которых обслуживает определенный набор путей. Это полезно, когда в приложении есть группы страниц, не связанных с другими страницами. Переместив эти страницы в отдельную зону (т.е. отдельное приложение), вы можете уменьшить размер каждого приложения, что улучшит время сборки и удалит код, необходимый только для одной из зон. Поскольку приложения разделены, Multi-Zones также позволяет другим приложениям на домене использовать собственный выбор фреймворка.

Например, предположим, у вас есть следующий набор страниц, которые вы хотите разделить:

  • /blog/* для всех постов блога
  • /dashboard/* для всех страниц, когда пользователь вошел в панель управления
  • /* для остальной части вашего сайта, не охваченной другими зонами

С поддержкой Multi-Zones вы можете создать три приложения, которые все обслуживаются на одном домене и выглядят одинаково для пользователя, но вы можете разрабатывать и развертывать каждое из приложений независимо.

Три зоны: A, B, C. Показывает жесткую навигацию между маршрутами из разных зон и мягкую навигацию между маршрутами в одной зоне.

Навигация между страницами в одной зоне будет выполнять мягкие переходы (soft navigation) — навигацию без перезагрузки страницы. Например, на этой диаграмме переход с / на /products будет мягким.

Навигация со страницы в одной зоне на страницу в другой зоне, например с / на /dashboard, будет выполнять жесткий переход (hard navigation), выгружая ресурсы текущей страницы и загружая ресурсы новой страницы. Страницы, которые часто посещаются вместе, должны находиться в одной зоне, чтобы избежать жестких переходов.

Как определить зону

Зона — это обычное Next.js-приложение, в котором также настроен assetPrefix, чтобы избежать конфликтов со страницами и статическими файлами в других зонах.

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  assetPrefix: '/blog-static',
}

Ресурсы Next.js, такие как JavaScript и CSS, будут иметь префикс assetPrefix, чтобы гарантировать отсутствие конфликтов с ресурсами из других зон. Эти ресурсы будут обслуживаться по пути /assetPrefix/_next/... для каждой из зон.

Главное приложение, обрабатывающее все пути, не направленные в другие более специфичные зоны, не требует assetPrefix.

В версиях Next.js старше 15 может потребоваться дополнительное правило перезаписи для обработки статических ресурсов. В Next.js 15 это больше не требуется.

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  assetPrefix: '/blog-static',
  async rewrites() {
    return {
      beforeFiles: [
        {
          source: '/blog-static/_next/:path+',
          destination: '/_next/:path+',
        },
      ],
    }
  },
}

Как направлять запросы в нужную зону

При настройке Multi-Zones вам нужно направлять пути в правильную зону, так как они обслуживаются разными приложениями. Вы можете использовать любой HTTP-прокси для этого, но одно из Next.js-приложений также может использоваться для маршрутизации запросов для всего домена.

Для маршрутизации в правильную зону с использованием Next.js-приложения вы можете использовать rewrites. Для каждого пути, обслуживаемого другой зоной, вы добавляете правило перезаписи, чтобы отправить этот путь на домен другой зоны, а также нужно перезаписывать запросы для статических ресурсов. Например:

next.config.js
async rewrites() {
    return [
        {
            source: '/blog',
            destination: `${process.env.BLOG_DOMAIN}/blog`,
        },
        {
            source: '/blog/:path+',
            destination: `${process.env.BLOG_DOMAIN}/blog/:path+`,
        },
        {
            source: '/blog-static/:path+',
            destination: `${process.env.BLOG_DOMAIN}/blog-static/:path+`,
        }
    ];
}

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

Важно знать: URL-пути должны быть уникальными для зоны. Например, две зоны, пытающиеся обслуживать /blog, создадут конфликт маршрутизации.

Маршрутизация запросов с использованием middleware

Рекомендуется маршрутизировать запросы через rewrites, чтобы минимизировать задержку, но middleware также может использоваться, когда требуется динамическое решение при маршрутизации. Например, если вы используете feature-флаг для определения, куда должен быть направлен путь, например во время миграции, вы можете использовать middleware.

middleware.js
export async function middleware(request) {
  const { pathname, search } = req.nextUrl;
  if (pathname === '/your-path' && myFeatureFlag.isEnabled()) {
    return NextResponse.rewrite(`${rewriteDomain}${pathname}${search});
  }
}

Ссылки между зонами

Ссылки на пути в другой зоне должны использовать тег a вместо Next.js-компонента <Link>. Это связано с тем, что Next.js попытается предварительно загрузить и выполнить мягкий переход для любого относительного пути в компоненте <Link>, что не будет работать между зонами.

Общий код

Next.js-приложения, составляющие разные зоны, могут находиться в любом репозитории. Однако часто удобно размещать эти зоны в монорепозитории, чтобы легче делиться кодом. Для зон, находящихся в разных репозиториях, код также можно делиться с помощью публичных или приватных NPM-пакетов.

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