Bỏ qua để đến nội dung

Sử dụng với Next.js

FSD tương thích với Next.js trong cả phiên bản App Router và Pages Router nếu bạn giải quyết được xung đột chính — thư mục apppages.

Xung đột giữa FSD và Next.js trong layer app

Phần tiêu đề “Xung đột giữa FSD và Next.js trong layer app”

Next.js đề xuất sử dụng thư mục app để định nghĩa các route của ứng dụng. Nó mong đợi các file trong thư mục app tương ứng với các pathname. Cơ chế routing này không phù hợp với khái niệm FSD, vì không thể duy trì cấu trúc slice phẳng.

Giải pháp là di chuyển thư mục app của Next.js vào thư mục gốc của dự án và import các pages FSD từ src, nơi chứa các layer FSD, vào thư mục app của Next.js.

Bạn cũng cần thêm thư mục pages vào thư mục gốc của dự án, nếu không Next.js sẽ cố gắng sử dụng src/pages như Pages Router ngay cả khi bạn sử dụng App Router, điều này sẽ làm hỏng quá trình build. Cũng nên đặt file README.md bên trong thư mục pages gốc này để mô tả tại sao nó cần thiết, mặc dù nó trống.

  • Thư mụcapp App folder (Next.js)
    • Thư mụcapi
      • Thư mụcget-example
        • route.ts
    • Thư mụcexample
      • page.tsx
  • Thư mụcpages Empty pages folder (Next.js)
    • README.md
  • Thư mụcsrc
    • Thư mụcapp
      • api-routes API routes
    • Thư mụcpages
      • Thư mụcexample
        • index.ts
        • Thư mụcui
          • example.tsx
    • Thư mụcwidgets/
    • Thư mụcfeatures/
    • Thư mụcentities/
    • Thư mụcshared/

Ví dụ về việc re-export một page từ src/pages trong app của Next.js:

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

Nếu bạn sử dụng middleware trong dự án, nó phải được đặt ở thư mục gốc của dự án cùng với thư mục apppages của Next.js.

File instrumentation.js cho phép bạn giám sát hiệu suất và hành vi của ứng dụng. Nếu bạn sử dụng nó, nó phải được đặt ở thư mục gốc của dự án, tương tự như middleware.js.

Xung đột giữa FSD và Next.js trong layer pages

Phần tiêu đề “Xung đột giữa FSD và Next.js trong layer pages”

Các route nên được đặt trong thư mục pages ở thư mục gốc của dự án, tương tự như thư mục app cho App Router. Cấu trúc bên trong src nơi các thư mục layer được đặt vẫn không thay đổi.

  • Thư mụcpages Pages folder (Next.js)
    • _app.tsx
    • Thư mụcapi
      • example.ts API route re-export
    • Thư mụcexample
      • index.tsx
  • Thư mụcsrc
    • Thư mụcapp
      • Thư mụccustom-app
        • custom-app.tsx Custom App component
      • Thư mụcapi-routes
        • get-example-data.ts API route
    • Thư mụcpages
      • Thư mụcexample
        • index.ts
        • Thư mụcui
          • example.tsx
    • Thư mụcwidgets/
    • Thư mụcfeatures/
    • Thư mụcentities/
    • Thư mụcshared/

Ví dụ về việc re-export một page từ src/pages trong pages của Next.js:

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

Bạn có thể đặt Custom App component của mình trong src/app/_app hoặc 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';

Sử dụng segment api-routes trong layer app để làm việc với Route Handlers.

Hãy chú ý khi viết code backend trong cấu trúc FSD — FSD chủ yếu dành cho frontend, nghĩa là đó là điều mà mọi người sẽ mong đợi tìm thấy. Nếu bạn cần nhiều endpoint, hãy cân nhắc tách chúng thành một package khác trong một monorepo.

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';
  • Sử dụng segment db trong layer shared để mô tả các database query và việc sử dụng chúng ở các layer cao hơn.
  • Logic caching và revalidating queries tốt nhất nên được giữ cùng chỗ với các query.