Next.js 13 での App ディレクトリの仕組み

Next.js 13 での App ディレクトリの仕組み

Next.js 13 では、アプリ ディレクトリを使用した新しいルーティング システムが導入されました。Next.js 12 では、ファイルベースのルートを介してルートを処理する簡単な方法が既に提供されています。コンポーネントをページ フォルダーに追加すると、自動的にルートになります。この新しいバージョンでは、ファイル システム ベースのルーターに、レイアウト、テンプレートのネストされたルーティング、読み込み UI、エラー処理、およびサーバー コンポーネントとストリーミングのサポートのための組み込みセットアップが付属しています。

この記事では、これらの新機能とその重要性について説明します。

Next.js 13 を使ってみる

ターミナルで次のコマンドを実行して、独自の Next.js 13 プロジェクトを作成します。

npx create-next-app@latest next13 --experimental-app

これにより、新しい app ディレクトリを含む next13 という新しいフォルダーが作成されます。

新しい App ディレクトリについて

Next.js 12ではルーティングにpagesディレクトリを使用していましたが、Next.js 13ではapp/ディレクトリに置き換えられています。エラーが発生するため、同じルートの 2 つのディレクトリにファイルを作成しないようにする必要があるだけです。

app ディレクトリの現在の構造は次のとおりです。

Next.js 13 ファイル構造

アプリ ディレクトリでは、フォルダーを使用してルートを定義し、これらのフォルダー内のファイルを使用して UI を定義します。次のような特別なファイルもあります。

  • page.tsx – 特定のルートの UI を作成するために使用されるファイル。
  • layout.tsx – ルートのレイアウト定義が含まれており、複数のページで共有できます。ナビゲーション メニューやサイドバーに最適です。ナビゲーションでは、レイアウトは状態を保持し、再レンダリングしません。つまり、レイアウトを共有するページ間を移動しても、状態は同じままです。注意すべきことの 1 つは、アプリケーション全体で共有されるすべての HTML タグと body タグを含む最上位のレイアウト (ルート レイアウト) が必要であるということです。
  • template.tsx –テンプレートはレイアウトに似ていますが、状態を保持せず、ページの作成に使用されるたびに再レンダリングされます。テンプレートは、コンポーネントがマウントされるたびに特定のコードを実行する必要がある場合に最適です。たとえば、アニメーションの開始と終了などです。
  • error.tsx –このファイルは、アプリケーションのエラーを処理するために使用されます。React エラー境界クラスでルートをラップし、そのルートまたはその子でエラーが発生した場合に、ユーザー フレンドリーなエラー ページをレンダリングすることでルートからの回復を試みます。
  • loading.tsx –ローディング UI は、ルート UI がバックグラウンドで読み込まれると、サーバーから即座に読み込まれます。ローディング UI は、スピナーまたはスケルトン画面にすることができます。ルート コンテンツが読み込まれると、読み込み UI が置き換えられます。
  • not-found.tsx – Next.jsでそのページの 404 エラーが発生すると、not-found ファイルがレンダリングされます。Next.js 12 では、404 ページを手動で作成して設定する必要がありました。
  • head.tsx –このファイルは、定義されているルート セグメントの head タグを指定します。

Next.js 13 でルートを作成する方法

前に述べたように、ルートはapp/ディレクトリ内のフォルダーを使用して作成されます。このフォルダー内に、その特定のルートの UI を定義するpage.tsxというファイルを作成する必要があります。

たとえば、パス/productsでルートを作成するには、 app/products/page.tsxファイルを作成する必要があります。

/products/saleのようなネストされたルートの場合、フォルダー構造がapp/products/sale/page.tsxのようになるようにフォルダーを相互にネストします。

ルーティングの新しい方法の他に、アプリ ディレクトリがサポートするその他の興味深い機能は、サーバー コンポーネントとストリーミングです。

App ディレクトリでサーバー コンポーネントを使用する

アプリ ディレクトリは、デフォルトでサーバー コンポーネントを使用します。このアプローチにより、コンポーネントがサーバー上でレンダリングされるときにブラウザーに送信される JavaScript の量が削減されます。これにより、パフォーマンスが向上します。

より詳細な説明については、Next.js のさまざまなレンダリング方法に関するこの記事を参照してください。

サーバー コンポーネントとは、クライアント側に公開されることなく、環境シークレットに安全にアクセスできることを意味します。たとえば、process.envを使用できます。

バックエンドと直接対話することもできます。サーバー コンポーネントで async/await を使用してデータを取得できるため、getServerSidePropsまたはgetStaticPropsを使用する必要はありません。

API からデータを取得するこの非同期関数について考えてみましょう。

async function getData() {
  try{
    const res = await fetch('https://api.example.com/...');
    return res.json();
  } catch(error) {
throw new Error('Could not fetch data')
  }
}

次のように、ページで直接呼び出すことができます。

export default async function Page() {
  const data = await getData();
  return <div></div>;
}

サーバー コンポーネントは、非対話型コンテンツのレンダリングに最適です。React フック、イベント リスナー、またはブラウザー専用 API を使用する必要がある場合は、インポートの前にコンポーネントの先頭に「use client」ディレクティブを追加して、クライアント コンポーネントを使用します。

App ディレクトリでコンポーネントを段階的にストリーミングする

ストリーミングとは、すべてのコンポーネントがレンダリングされるまで、UI の一部をクライアントに段階的に送信することを指します。これにより、ユーザーはコンテンツの一部を表示しながら、残りの部分をレンダリングできます。ユーザーのエクスペリエンスを向上させるには、サーバーがコンテンツのレンダリングを完了するまで、読み込み中のコンポーネントをスピナーのようにレンダリングします。これを行うには、次の 2 つの方法を使用します。

  • ルート セグメント全体に対してレンダリングされるloading.tsxファイルを作成します。

export default function Loading() {
  return <p>Loading...</p>
}

  • 個々のコンポーネントを React Suspense 境界でラップし、フォールバック UI を指定します。

import { Suspense } from "react";
import { Products } from "./Components";

export default function Sale() {
  return (
    <section>
      <Suspense fallback={<p>Products...</p>}>
        <Products />
      </Suspense>
    </section>
  );
}

Products コンポーネントがレンダリングされる前に、ユーザーには「Products…」が表示されます。これは、ユーザー エクスペリエンスの点で空白の画面よりも優れています。

Next.js 13 へのアップグレード

新しいアプリ ディレクトリは、以前のページ ディレクトリから確実に改善されています。これには、レイアウト、ヘッド、テンプレート、エラー、not-found、およびロードなどの特別なファイルが含まれており、手動設定を必要とせずにルートをレンダリングするときにさまざまな状態を処理します。

さらに、アプリ ディレクトリはストリーミングと、パフォーマンスの向上につながるサーバー コンポーネントもサポートしています。これらの機能はユーザーと開発者の両方にとって優れていますが、現在、ほとんどの機能はベータ版です。

ただし、ページ ディレクトリは引き続き機能するため、Next.js 13 にアップグレードしてから、自分のペースでアプリ ディレクトリを使い始めることができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です