@@ -4,109 +4,199 @@ sidebar:
44 order : 1
55---
66
7- import { Tabs , TabItem , FileTree } from ' @astrojs/starlight/components' ;
7+ import { Tabs , TabItem , FileTree , Aside } from ' @astrojs/starlight/components' ;
88
9- NextJSプロジェクトでFSDを実装することは可能ですが、プロジェクトの構造に関するNextJSの要件とFSDの原則の間に2つの点で対立が生じます。
9+ <Aside type = " caution" >
10+ 競合を避けるため、使用するルーターに関わらず、` app ` と` pages ` の** 両方** のFSD層を` _app ` と` _pages ` に名前変更してください。
11+ </Aside >
1012
11- - ` pages ` のファイルルーティング
12- - NextJSにおける` app ` の対立、または欠如
13+ ## srcフォルダー
1314
14- ## ` pages ` におけるFSDとNextJSの対立 \{ # pages-conflict}
15+ NextJSは、プロジェクトのルートまたは ` src ` フォルダーのいずれかに、特別な ` app ` または ` pages ` フォルダーを期待します。一般的には、 ` src ` フォルダーにFSDコードのみが含まれるように、NextJSのフォルダーをプロジェクトのルートに配置する方が簡単ですが、必須ではありません。
1516
16- NextJSは、アプリケーションのルートを定義するために ` pages ` フォルダーを使用することを提案しています。 ` pages ` フォルダー内のファイルがURLに対応することを期待しています。このルーティングメカニズムは、FSDの概念に ** 適合しません ** 。なぜなら、このようなルーティングメカニズムでは、スライスの平坦な構造を維持することができないからです。
17+ ## App Router \{ #app-router \}
1718
18- ### NextJSの` pages ` フォルダーをプロジェクトのルートフォルダーに移動する(推奨)
19-
20- このアプローチは、NextJSの` pages ` フォルダーをプロジェクトのルートフォルダーに移動し、FSDのページをNextJSの` pages ` フォルダーにインポートすることにあります。これにより、` src ` フォルダー内でFSDのプロジェクト構造を維持できます。
19+ NextJSはApp Routerに` app ` フォルダーを、Pages Routerに` pages ` フォルダーを使用しますが、これはFSDの層名と競合します。この競合を解決するには、` app ` の代わりに` _app ` 、` pages ` の代わりに` _pages ` のように、FSD層にプレフィックス付きの名前を使用してください。このアプローチは公式の[ リンター] ( https://github.com/feature-sliced/steiger ) とも互換性があります。
2120
2221<FileTree >
23- - pages NextJSのpagesフォルダー
24- - src
25- - app
26- - entities
27- - features
28- - pages FSDのpagesフォルダー
29- - shared
30- - widgets
22+ - app NextJSのappフォルダー
23+ - api/
24+ - get-example/
25+ - route.ts
26+ - example/
27+ - page.tsx
28+ - src/
29+ - _ app/ FSD層
30+ - api-routes/ APIルート
31+ - _ pages/ FSD層
32+ - example/
33+ - index.ts
34+ - ui/
35+ - example.tsx
36+ - widgets/
37+ - features/
38+ - entities/
39+ - shared/
3140</FileTree >
3241
33- ### FSD構造における` pages ` フォルダーの名前変更
42+ NextJSの` app ` 内で` src/_pages ` からページを再エクスポートする例:
43+
44+ ``` tsx title="app/example/page.tsx"
45+ export { ExamplePage as default , metadata } from ' @/_pages/example' ;
46+ ```
47+
48+ ### サーバーとクライアントのパブリックAPI \{ #server-and-client-public-apis\}
49+
50+ NextJSのApp Routerでは、クライアントで使用できるモジュールとサーバー専用のモジュールが、1つのスライス内に共存することがあります。サーバー専用のモジュールが` index.ts ` からエクスポートされている場合、クライアントコンポーネントがそのスライスをインポートすると、サーバー専用の副作用がクライアントのモジュールグラフに伝播し、ビルドエラーにつながる可能性があります。
51+
52+ この問題が発生した場合は、パブリックAPIに` index.server.ts ` を追加してください。
53+
54+ - ` index.server.ts ` : サーバーコンポーネントや` server-only ` でマークされたデータアクセス関数など、サーバーでのみインポートされる必要があるモジュール
55+
56+ ### Middleware \{ #middleware\}
57+
58+ プロジェクトでミドルウェアを使用する場合は、NextJSの` app ` および` pages ` フォルダーと並んでプロジェクトのルートに配置する必要があります。
59+
60+ ### Instrumentation \{ #instrumentation\}
61+
62+ ` instrumentation.js ` ファイルを使用すると、アプリケーションのパフォーマンスと動作を監視できます。使用する場合は、` middleware.js ` と同様にプロジェクトのルートに配置する必要があります。
3463
35- もう一つの解決策は、FSD構造内の` pages ` 層の名前を変更して、NextJSの` pages ` フォルダーとの名前衝突を避けることです。
36- FSDの` pages ` 層を` views ` 層に変更することができます。
37- このようにすることで、` src ` フォルダー内のプロジェクト構造は、NextJSの要件と矛盾することなく保持されます。
64+ ## Pages Router \{ #pages-router\}
3865
66+ ### ` pages ` 層におけるFSDとNextJSの競合 \{ #conflict-between-fsd-and-nextjs-in-the-pages-layer\}
67+
68+ App Routerの` app ` フォルダーと同様に、ルートはプロジェクトのルートにある` pages ` フォルダーに配置する必要があります。層フォルダーが配置されている` src ` 内の構造は変わりません。
3969
4070<FileTree >
41- - app
42- - entities
43- - features
44- - pages NextJSのpagesフォルダー
45- - views 名前が変更されたFSDのページフォルダー
46- - shared
47- - widgets
71+ - pages/ pagesフォルダー(NextJS)
72+ - _ app.tsx
73+ - api/
74+ - example.ts APIルートの再エクスポート
75+ - example/
76+ - index.tsx
77+ - src/
78+ - _ app/ FSD層
79+ - custom-app/
80+ - custom-app.tsx カスタムAppコンポーネント
81+ - api-routes/
82+ - get-example-data.ts APIルート
83+ - _ pages/ FSD層
84+ - example/
85+ - index.ts
86+ - ui/
87+ - example.tsx
88+ - widgets/
89+ - features/
90+ - entities/
91+ - shared/
4892</FileTree >
4993
50- この場合、プロジェクトのREADMEや内部ドキュメントなど、目立つ場所にこの名前変更を文書化することをお勧めします。この名前変更は、 [ 「プロジェクト知識」 ] [ project-knowledge ] の一部です。
94+ NextJSの ` pages ` 内で ` src/_pages ` からページを再エクスポートする例:
5195
52- ## NextJSにおける` app ` フォルダーの欠如 \{ #app-absence}
96+ ``` tsx title="pages/example/index.tsx"
97+ export { Example as default } from ' @/_pages/example' ;
98+ ```
99+
100+ ### カスタム` _app ` コンポーネント \{ #custom-_ app-component\}
101+
102+ カスタムAppコンポーネントは` src/_app/_app ` または` src/_app/custom-app ` に配置できます:
53103
54- NextJSのバージョン13未満では、明示的な` app ` フォルダーは存在せず、代わりにNextJSは` _app.tsx ` ファイルを提供しています。このファイルは、プロジェクトのすべてのページのラッピングコンポーネントとして機能しています。
104+ ``` tsx title="src/_app/custom-app/custom-app.tsx"
105+ import type { AppProps } from ' next/app' ;
55106
56- ### ` pages/_app.tsx ` ファイルへの機能のインポート
107+ export const MyApp = ({ Component , pageProps }: AppProps ) => {
108+ return (
109+ <>
110+ <p >My Custom App component</p >
111+ <Component { ... pageProps } />
112+ </>
113+ );
114+ };
115+ ```
57116
58- NextJSの構造における` app ` フォルダーの欠如の問題を解決するために、` app ` 層内に` App ` コンポーネントを作成し、NextJSがそれを使用できるように` pages/_app.tsx ` に` App ` コンポーネントをインポートすることができます。例えば
117+ ``` tsx title="pages/_app.tsx"
118+ export { App as default } from ' @/_app/custom-app' ;
119+ ```
59120
121+ ## ルートハンドラー(APIルート) \{ #route-handlers-api-routes\}
60122
61- ``` tsx
62- // app/providers/index.tsx
123+ ルートハンドラーを扱うには、` _app ` 層の` api-routes ` セグメントを使用します。
63124
64- const App = ({ Component , pageProps }: AppProps ) => {
65- return (
66- <Provider1 >
67- <Provider2 >
68- <BaseLayout >
69- <Component { ... pageProps } />
70- </BaseLayout >
71- </Provider2 >
72- </Provider1 >
73- );
125+ FSD構造内でバックエンドのコードを書く際は注意してください。FSDは主にフロントエンドを対象としており、それが人々が見つけることを期待するものだからです。
126+ 多くのエンドポイントが必要な場合は、モノレポ内の別のパッケージに分離することを検討してください。
127+
128+ <Tabs >
129+
130+ <TabItem value = " app-router" label = " App Router" >
131+
132+ ``` tsx title="src/_app/api-routes/get-example-data.ts"
133+ import { getExamplesList } from ' @/shared/db' ;
134+
135+ export const getExampleData = () => {
136+ try {
137+ const examplesList = getExamplesList ();
138+
139+ return Response .json ({ examplesList });
140+ } catch {
141+ return Response .json (null , {
142+ status: 500 ,
143+ statusText: ' Ouch, something went wrong' ,
144+ });
145+ }
74146};
147+ ```
75148
76- export default App ;
149+ ``` tsx title="app/api/example/route.ts"
150+ export { getExampleData as GET } from ' @/_app/api-routes' ;
77151```
78- その後、` App ` コンポーネントとプロジェクトのグローバルスタイルを` pages/_app.tsx ` に次のようにインポートできます。
79152
80- ``` tsx
81- // pages/_app.tsx
153+ </TabItem >
82154
83- import ' app/styles/index.scss '
155+ < TabItem value = " pages-router " label = " Pages Router " >
84156
85- export { default } from ' app/providers' ;
157+ ``` tsx title="src/_app/api-routes/get-example-data.ts"
158+ import type { NextApiRequest , NextApiResponse } from ' next' ;
159+
160+ const config = {
161+ api: {
162+ bodyParser: {
163+ sizeLimit: ' 1mb' ,
164+ },
165+ },
166+ maxDuration: 5 ,
167+ };
168+
169+ const handler = (req : NextApiRequest , res : NextApiResponse <ResponseData >) => {
170+ res .status (200 ).json ({ message: ' Hello from FSD' });
171+ };
172+
173+ export const getExampleData = { config , handler } as const ;
86174```
87175
176+ ``` tsx title="src/_app/api-routes/index.ts"
177+ export { getExampleData } from ' ./get-example-data' ;
178+ ```
88179
89- ## App Routerの使用 \{ #app-router}
180+ ``` tsx title="app/api/example.ts"
181+ import { getExampleData } from ' @/_app/api-routes' ;
90182
91- App Routerは、Next.jsのバージョン13.4で安定版として登場しました。App Routerを使用すると、` pages ` フォルダーの代わりに` app ` フォルダーをルーティングに使用できます。
92- FSDの原則に従うために、NextJSの` app ` フォルダーを` pages ` フォルダーとの名前衝突を解消するために推奨される方法で扱うべきです。
183+ export const config = getExampleData .config ;
184+ export default getExampleData .handler ;
185+ ```
93186
94- このアプローチは、NextJSの ` app ` フォルダーをプロジェクトのルートフォルダーに移動し、FSDのページをNextJSの ` app ` フォルダーにインポートすることに基づいています。これにより、 ` src ` フォルダー内のFSDプロジェクト構造が保持されます。また、プロジェクトのルートフォルダーに ` pages ` フォルダーを追加することもお勧めします。なぜなら、App RouterはPages Routerと互換性があるからです。
187+ </ TabItem >
95188
96- <FileTree >
97- - app/ NextJSのappフォルダー
98- - pages/ 空のNextJSのpagesフォルダー
99- - README.md このフォルダーの目的に関する説明
100- - src/
101- - app/ FSDのappフォルダー
102- - entities/
103- - features/
104- - pages/ FSDのpagesフォルダー
105- - shared/
106- - widgets/
107- </FileTree >
189+ </Tabs >
190+
191+ ## 追加の推奨事項 \{ #additional-recommendations\}
192+
193+ - データベースクエリの記述と上位層でのその利用には、` shared ` 層の` db ` セグメントを使用してください。
194+ - クエリのキャッシュと再検証のロジックは、クエリ自体と同じ場所に保持する方が良いでしょう。
195+
196+ ## 関連項目 \{ #see-also\}
108197
109- [ ![ StackBlitzで開く] ( https://developer.stackblitz.com/img/open_in_stackblitz.svg )] [ ext-app-router-stackblitz ]
198+ - [ NextJSのプロジェクト構造] ( https://nextjs.org/docs/app/getting-started/project-structure )
199+ - [ NextJSのページレイアウト] ( https://nextjs.org/docs/app/getting-started/layouts-and-pages )
110200
111201[ project-knowledge ] : /ja/docs/about/understanding/knowledge-types
112202[ ext-app-router-stackblitz ] : https://stackblitz.com/edit/stackblitz-starters-aiez55?file=README.md
0 commit comments