マルチゾーン (Multi-Zones)

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

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

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

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

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

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

一方、あるゾーンのページから別のゾーンのページへ移動する場合(例えば/から/dashboardへ)は、現在のページのリソースをアンロードし、新しいページのリソースをロードするハードナビゲーションが実行されます。頻繁に一緒に訪問されるページは、ハードナビゲーションを避けるために同じゾーンに配置すべきです。

ゾーンの定義方法

新しいゾーンを定義する特別なAPIはありません。ゾーンは通常のNext.jsアプリケーションであり、他のゾーンのページや静的ファイルとの衝突を避けるためにbasePathを設定します。

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

より特定のゾーンに送信されないすべてのパスを処理するデフォルトのアプリケーションには、basePathは必要ありません。

Next.jsのアセット(JavaScriptやCSSなど)も、他のゾーンのアセットと衝突しないようにbasePathがプレフィックスとして付与されます。これらのアセットは、各ゾーンごとに/basePath/_next/...の下で提供されます。

ゾーンが/home/blogのように共通のパスプレフィックスを共有しないページを提供する場合、アプリケーションの残りのルートにパスプレフィックスを追加せずに、ゾーンのすべてのNext.jsアセットが一意のパスプレフィックスの下で提供されるようにassetPrefixを設定することもできます。

リクエストを適切なゾーンにルーティングする方法

マルチゾーン設定では、異なるアプリケーションによって提供されるため、パスを正しいゾーンにルーティングする必要があります。任意の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を提供しようとすると、ルーティングの競合が発生します。

ゾーン間のリンク

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

コードの共有

異なるゾーンを構成するNext.jsアプリケーションは、任意のリポジトリに配置できます。ただし、コードを簡単に共有できるように、これらのゾーンをモノレポに配置することがよくあります。異なるリポジトリにあるゾーンの場合、公開または非公開のNPMパッケージを使用してコードを共有することもできます。

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

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