メインコンテンツにスキップ

NextJSとの併用

注意

競合を避けるため、使用するルーターに関わらず、apppages両方のFSD層を_app_pagesに名前変更してください。

srcフォルダー

NextJSは、プロジェクトのルートまたはsrcフォルダーのいずれかに、特別なappまたはpagesフォルダーを期待します。一般的には、srcフォルダーにFSDコードのみが含まれるように、NextJSのフォルダーをプロジェクトのルートに配置する方が簡単ですが、必須ではありません。

App Router

NextJSはApp Routerにappフォルダーを、Pages Routerにpagesフォルダーを使用しますが、これはFSDの層名と競合します。この競合を解決するには、appの代わりに_apppagesの代わりに_pagesのように、FSD層にプレフィックス付きの名前を使用してください。このアプローチは公式のリンターとも互換性があります。

├── app                              # NextJSのappフォルダー
│ ├── api
│ │ └── get-example
│ │ └── route.ts
│ └── example
│ └── page.tsx
└── src
├── _app # FSD層
│ └── api-routes # APIルート
├── _pages # FSD層
│ └── example
│ ├── index.ts
│ └── ui
│ └── example.tsx
├── widgets
├── features
├── entities
└── shared

NextJSのapp内でsrc/_pagesからページを再エクスポートする例:

app/example/page.tsx
export { ExamplePage as default, metadata } from '@/_pages/example';

サーバーとクライアントのパブリックAPI

NextJSのApp Routerでは、クライアントで使用できるモジュールとサーバー専用のモジュールが、1つのスライス内に共存することがあります。サーバー専用のモジュールがindex.tsからエクスポートされている場合、クライアントコンポーネントがそのスライスをインポートすると、サーバー専用の副作用がクライアントのモジュールグラフに伝播し、ビルドエラーにつながる可能性があります。

この問題が発生した場合は、パブリックAPIにindex.server.tsを追加してください。

  • index.server.ts: サーバーコンポーネントやserver-onlyでマークされたデータアクセス関数など、サーバーでのみインポートされる必要があるモジュール

Middleware

プロジェクトでミドルウェアを使用する場合は、NextJSのappおよびpagesフォルダーと並んでプロジェクトのルートに配置する必要があります。

Instrumentation

instrumentation.jsファイルを使用すると、アプリケーションのパフォーマンスと動作を監視できます。使用する場合は、middleware.jsと同様にプロジェクトのルートに配置する必要があります。

Pages Router

pages層におけるFSDとNextJSの競合

App Routerのappフォルダーと同様に、ルートはプロジェクトのルートにあるpagesフォルダーに配置する必要があります。層フォルダーが配置されているsrc内の構造は変わりません。

├── pages                            # pagesフォルダー(NextJS)
│ ├── _app.tsx
│ ├── api
│ │ └── example.ts # APIルートの再エクスポート
│ └── example
│ └── index.tsx
└── src
├── _app # FSD層
│ ├── custom-app
│ │ └── custom-app.tsx # カスタムAppコンポーネント
│ └── api-routes
│ └── get-example-data.ts # APIルート
├── _pages # FSD層
│ └── example
│ ├── index.ts
│ └── ui
│ └── example.tsx
├── widgets
├── features
├── entities
└── shared

NextJSのpages内でsrc/_pagesからページを再エクスポートする例:

pages/example/index.tsx
export { Example as default } from '@/_pages/example';

カスタム_appコンポーネント

カスタムAppコンポーネントはsrc/_app/_appまたはsrc/_app/custom-appに配置できます:

src/_app/custom-app/custom-app.tsx
import type { AppProps } from 'next/app';

export const MyApp = ({ Component, pageProps }: AppProps) => {
return (
<>
<p>My Custom App component</p>
<Component { ...pageProps } />
</>
);
};
pages/_app.tsx
export { App as default } from '@/_app/custom-app';

ルートハンドラー(APIルート)

ルートハンドラーを扱うには、_app層のapi-routesセグメントを使用します。

FSD構造内でバックエンドのコードを書く際は注意してください。FSDは主にフロントエンドを対象としており、それが人々が見つけることを期待するものだからです。 多くのエンドポイントが必要な場合は、モノレポ内の別のパッケージに分離することを検討してください。

src/_app/api-routes/get-example-data.ts
import { getExamplesList } from '@/shared/db';

export const getExampleData = () => {
try {
const examplesList = getExamplesList();

return Response.json({ examplesList });
} catch {
return Response.json(null, {
status: 500,
statusText: 'Ouch, something went wrong',
});
}
};
app/api/example/route.ts
export { getExampleData as GET } from '@/_app/api-routes';

追加の推奨事項

  • データベースクエリの記述と上位層でのその利用には、shared層のdbセグメントを使用してください。
  • クエリのキャッシュと再検証のロジックは、クエリ自体と同じ場所に保持する方が良いでしょう。

関連項目