コンテンツにスキップ

マルチゾーン

マルチゾーンは、ドメイン上の大規模なアプリケーションを、それぞれがパスのセットを提供する小さなNext.jsアプリケーションに分割するマイクロフロントエンドのアプローチです。これは、アプリケーション内の他のページと関係のないページのコレクションがある場合に役立ちます。これらのページを別のゾーン(つまり、別のアプリケーション)に移動することで、各アプリケーションのサイズを削減でき、ビルド時間を短縮し、特定のゾーンにのみ必要なコードを削除できます。アプリケーションは切り離されているため、マルチゾーンではドメイン上の他のアプリケーションが独自のフレームワークを選択することもできます。

例えば、分割したい以下のページセットがあるとします。

  • すべてのブログ投稿用の/blog/*
  • ユーザーがダッシュボードにログインしている場合のすべてのページ用の/dashboard/*
  • 他のゾーンでカバーされていない残りのウェブサイト用の/*

マルチゾーンのサポートにより、同じドメインで提供され、ユーザーには同じに見える3つのアプリケーションを作成できますが、各アプリケーションを独立して開発およびデプロイできます。

Three zones: A, B, C. Showing a hard navigation between routes from different zones, and soft navigations between routes within the same zone.

同じゾーン内のページ間を移動すると、ページのリロードを必要としないソフトナビゲーションが実行されます。たとえば、この図では、/から/productsへのナビゲーションはソフトナビゲーションになります。

/から/dashboardのように、あるゾーンのページから別のゾーンのページに移動すると、ハードナビゲーションが実行され、現在のページのリソースがアンロードされ、新しいページのリソースがロードされます。頻繁に一緒にアクセスされるページは、ハードナビゲーションを避けるために同じゾーンに配置する必要があります。

ゾーンの定義方法

ゾーンは通常の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+',
        },
      ],
    }
  },
}

リクエストを正しいゾーンにルーティングする方法

マルチゾーンのセットアップでは、パスが異なるアプリケーションによって提供されるため、正しいゾーンにルーティングする必要があります。これには任意のHTTPプロキシを使用できますが、Next.jsアプリケーションの1つをドメイン全体のリクエストをルーティングするために使用することもできます。

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+`,
        }
    ];
}

destinationは、スキームとドメインを含むゾーンによって提供されるURLである必要があります。これはゾーンの本番ドメインを指すべきですが、ローカル開発ではlocalhostへのリクエストのルーティングにも使用できます。

知っておくと良いこと:URLパスはゾーンごとに一意である必要があります。たとえば、2つのゾーンが/blogを提供しようとすると、ルーティングの競合が発生します。

ミドルウェアを使用したリクエストのルーティング

リクエストのレイテンシオーバーヘッドを最小限に抑えるには、rewritesを介したリクエストのルーティングが推奨されますが、ルーティング時に動的な決定が必要な場合は、ミドルウェアを使用することもできます。たとえば、移行中にパスをどこにルーティングするかを決定するために機能フラグを使用している場合、ミドルウェアを使用できます。

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

ゾーン間のリンク

異なるゾーン内のパスへのリンクは、Next.jsの<Link>コンポーネントではなく、aタグを使用する必要があります。これは、Next.jsが<Link>コンポーネント内の相対パスをプリフェッチしてソフトナビゲートしようとするためですが、これはゾーンをまたがる場合は機能しません。

コードの共有

異なるゾーンを構成するNext.jsアプリケーションは、どのリポジトリにも存在できます。しかし、コードをより簡単に共有するために、これらのゾーンをモノレポに入れると便利な場合が多いです。異なるリポジトリに存在するゾーンの場合、公開またはプライベートのNPMパッケージを使用してコードを共有することもできます。

異なるゾーンのページは異なる時期にリリースされる可能性があるため、機能フラグは異なるゾーン間で機能を統一的に有効または無効にするのに役立ちます。

Vercel上のNext.jsアプリケーションの場合、モノレポを使用して、git pushを1回行うだけで影響を受けるすべてのゾーンをデプロイできます。