与 Next.js 一起使用
如果您解决了主要冲突——app 和 pages 文件夹,FSD 与 Next.js 的 App Router 版本和 Pages Router 版本都兼容。
App Router
Section titled “App Router”FSD 和 Next.js 在 app 层中的冲突
Section titled “FSD 和 Next.js 在 app 层中的冲突”Next.js 建议使用 app 文件夹来定义应用程序路由。它期望 app 文件夹中的文件对应于路径名。这种路由机制与 FSD 概念不一致,因为无法维护扁平的 slice 结构。
解决方案是将 Next.js 的 app 文件夹移动到项目根目录,并将 FSD 页面从 src(FSD 层所在的位置)导入到 Next.js 的 app 文件夹中。
您还需要在项目根目录中添加一个 pages 文件夹,否则即使您使用 App Router,Next.js 也会尝试将 src/pages 用作 Pages Router,这会破坏构建。在这个根 pages 文件夹中放置一个 README.md 文件来描述为什么它是必要的也是一个好主意,即使它是空的。
文件夹app App folder (Next.js)
文件夹api
文件夹get-example
- route.ts
文件夹example
- page.tsx
文件夹pages Empty pages folder (Next.js)
- README.md
文件夹src
文件夹app
- api-routes API routes
文件夹pages
文件夹example
- index.ts
文件夹ui
- example.tsx
文件夹widgets/
- …
文件夹features/
- …
文件夹entities/
- …
文件夹shared/
- …
在 Next.js app 中从 src/pages 重新导出页面的示例:
export { ExamplePage as default, metadata } from '@/pages/example';如果您在项目中使用中间件,它必须位于项目根目录中,与 Next.js 的 app 和 pages 文件夹并列。
instrumentation.js 文件允许您监控应用程序的性能和行为。如果您使用它,它必须位于项目根目录中,类似于 middleware.js。
Pages Router
Section titled “Pages Router”FSD 和 Next.js 在 pages 层中的冲突
Section titled “FSD 和 Next.js 在 pages 层中的冲突”路由应该放在项目根目录的 pages 文件夹中,类似于 App Router 的 app 文件夹。src 内部层文件夹所在的结构保持不变。
文件夹pages Pages folder (Next.js)
- _app.tsx
文件夹api
- example.ts API route re-export
文件夹example
- index.tsx
文件夹src
文件夹app
文件夹custom-app
- custom-app.tsx Custom App component
文件夹api-routes
- get-example-data.ts API route
文件夹pages
文件夹example
- index.ts
文件夹ui
- example.tsx
文件夹widgets/
- …
文件夹features/
- …
文件夹entities/
- …
文件夹shared/
- …
在 Next.js pages 中从 src/pages 重新导出页面的示例:
export { Example as default } from '@/pages/example';自定义 _app 组件
Section titled “自定义 _app 组件”您可以将自定义 App 组件放在 src/app/_app 或 src/app/custom-app 中:
import type { AppProps } from 'next/app';
export const MyApp = ({ Component, pageProps }: AppProps) => { return ( <> <p>My Custom App component</p> <Component { ...pageProps } /> </> );};export { App as default } from '@/app/custom-app';路由处理程序(API 路由)
Section titled “路由处理程序(API 路由)”使用 app 层中的 api-routes segment 来处理路由处理程序。
在 FSD 结构中编写后端代码时要谨慎——FSD 主要用于前端,这意味着人们会期望找到前端代码。 如果您需要很多端点,请考虑将它们分离到 monorepo 中的不同包中。
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', }); }};export { getExampleData as GET } from '@/app/api-routes';import type { NextApiRequest, NextApiResponse } from 'next';
const config = { api: { bodyParser: { sizeLimit: '1mb', }, }, maxDuration: 5,};
const handler = (req: NextApiRequest, res: NextApiResponse<ResponseData>) => { res.status(200).json({ message: 'Hello from FSD' });};
export const getExampleData = { config, handler } as const;export { getExampleData } from './get-example-data';import { getExampleData } from '@/app/api-routes';
export const config = getExampleData.config;export default getExampleData.handler;Additional recommendations
Section titled “Additional recommendations”- Use the
dbsegment in thesharedlayer to describe database queries and their further use in higher layers. - Caching and revalidating queries logic is better kept in the same place as the queries themselves.