Next.js マルチゾーンを使用したマイクロフロントエンドの構築方法

サンプル

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

例えば、以下のようなページセットを分割したい場合を考えてみましょう:

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

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

3つのゾーン: A, B, C。異なるゾーン間のルート移動(ハードナビゲーション)と同一ゾーン内のルート移動(ソフトナビゲーション)を示す図

同一ゾーン内のページ間を移動する場合はソフトナビゲーション(ページの再読み込みを必要としないナビゲーション)が実行されます。例えば、この図では/から/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+`,
        },
        {
            source: '/blog-static/:path+',
            destination: `${process.env.BLOG_DOMAIN}/blog-static/: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パッケージを使用してコードを共有することもできます。

異なるゾーンのページは異なるタイミングでリリースされる可能性があるため、フィーチャーフラグを使用して、異なるゾーン間で一貫して機能を有効または無効にすると便利です。

サーバーアクション

マルチゾーンでサーバーアクションを使用する場合、ユーザー向けドメインが複数のアプリケーションを提供する可能性があるため、ユーザー向けオリジンを明示的に許可する必要があります。next.config.jsファイルに以下の行を追加します:

next.config.js
const nextConfig = {
  experimental: {
    serverActions: {
      allowedOrigins: ['your-production-domain.com'],
    },
  },
}

詳細についてはserverActions.allowedOriginsを参照してください。

On this page