コンテンツにスキップ

NextJSとの併用

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

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

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

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

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

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

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

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

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コンポーネントは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ルート)

Section titled “ルートハンドラー(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セグメントを使用してください。
  • クエリのキャッシュと再検証のロジックは、クエリ自体と同じ場所に保持する方が良いでしょう。