-
Notifications
You must be signed in to change notification settings - Fork 206
docs(guides): update next.js tech guide to the relevant status #830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c4bc798
7772df5
7ff2cd5
bd2be13
dd696f5
5d31344
cfa8efe
05f7010
3a361ab
60a9dbd
abd76d7
82514f5
a20b4ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,121 +1,118 @@ | ||
--- | ||
sidebar_position: 10 | ||
--- | ||
# Usage with NextJS | ||
# Usage with Next.js | ||
|
||
It is possible to implement FSD in a NextJS project, but conflicts arise due to differences between the requirements for the NextJS project structure and the principles of FSD in two points: | ||
It's possible to implement FSD in a Next.js project, but conflicts arise due to differences between Next.js project structure requirements and FSD principles. | ||
|
||
- Routing files in the `pages` layer | ||
- Conflict or absence of the `app` layer in NextJS | ||
## Conflict between FSD and Next.js in the `app` layer | ||
|
||
## Conflict between FSD and NextJS on `pages` layer {#pages-conflict} | ||
Next.js suggests using the `app` folder to define application routes. It expects files in the `app` folder to correspond to pathnames. | ||
This routing mechanism **does not align** with the FSD concept, as it's not possible to maintain a flat slice structure with such a routing mechanism. | ||
|
||
The approach is to move the Next.js `app` folder to the project root and import FSD pages into the Next.js `app` folder. | ||
This preserves the FSD project structure inside the `src` folder, where layer folders should be placed. | ||
|
||
NextJS suggests using the `pages` folder to define application routes. NextJS expects files in the `pages` folder to match URLs. | ||
This routing mechanism **does not correspond** to the FSD concept, since it is not possible to maintain a flat slice structure in such a routing mechanism. | ||
|
||
### Moving the `pages` folder of NextJS to the root folder of the project (recommended) | ||
|
||
The approach is to move the `pages` NextJS folder to the root folder of the project and import the FSD pages into the `pages` NextJS folder. This saves | ||
the FSD project structure inside the `src` folder. | ||
You should also add a `pages` folder to the project root because App Router is compatible with Pages Router. | ||
The best way is to put `README.md` file inside describing the need to save this folder. | ||
|
||
```sh | ||
├── pages # NextJS pages folder | ||
├── src | ||
│ ├── app | ||
│ ├── entities | ||
│ ├── features | ||
│ ├── pages # FSD pages folder | ||
│ ├── shared | ||
│ ├── widgets | ||
├── app # App folder (Next.js) | ||
├── api | ||
│ └── get-example | ||
│ └── route.ts | ||
│ └── example | ||
│ └── page.tsx | ||
├── pages # Legacy pages folder (Next.js) | ||
│ └── README.md # To maintain compatibility with Pages Router | ||
└── src | ||
├── app | ||
├── pages | ||
│ └── example | ||
│ ├── index.ts | ||
│ ├── ui | ||
│ │ └── example.tsx | ||
│ └── routes | ||
│ └── get-example.ts # Route handler | ||
├── widgets | ||
├── features | ||
├── entities | ||
└── shared | ||
``` | ||
|
||
### Renaming the `pages` layer within the FSD structure | ||
### Example of re-exporting a page from `src/pages/example` to `app/example/page.tsx` | ||
|
||
Another way to solve the problem is to rename the `pages` layer in the FSD structure to avoid conflicts with the NextJS `pages` folder. | ||
You can rename the `pages` layer in FSD to `views`. | ||
In that way, the structure of the project in the `src` folder is preserved without contradiction with the requirements of NextJS. | ||
|
||
```sh | ||
├── app | ||
├── entities | ||
├── features | ||
├── pages # NextJS pages folder | ||
├── views # Renamed FSD pages folder | ||
├── shared | ||
├── widgets | ||
```tsx title="app/example/page.tsx" | ||
export { Example as default, metadata } from '@/pages/example'; | ||
``` | ||
|
||
Keep in mind that it's highly recommended to document this rename prominently in your project's README or internal documentation. This rename is a part of your ["project knowledge"][project-knowledge]. | ||
|
||
## The absence of the `app` folder in NextJS {#app-absence} | ||
|
||
In NextJS below version 13, there is no explicit `app` folder, instead NextJS provides the `_app.tsx` file, | ||
which plays the role of a wrapping component for all project pages. | ||
|
||
### Importing app functionality to `pages/_app.tsx` file | ||
### Middleware | ||
If you use middleware in your project, it must be located in the project root alongside the `app` and `pages` folders. | ||
|
||
To solve the problem of missing the `app` folder in the NextJS structure, you can create an `App` component inside the `app` layer and import the `App` component into `pages/_app.tsx` so that NextJS can work with it. | ||
For example: | ||
### Instrumentation | ||
The `instrumentation.ts|js` file allows you to monitor the performance and behavior of your application. If you use it, it must be located in the project root, similar to `middleware.ts|js`. | ||
|
||
```tsx | ||
// app/providers/index.tsx | ||
### Route Handlers | ||
It is suggested to use a new `routes` segment in the `app` or `pages` layer to work with Route Handlers. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue: this part isn't clear to me. You mention that it's recommended to use the suggestion: let's also add a code block where But also, should this really be in the FSD structure? I feel like mixing in unrelated backend code into the frontend code folder might make it hard to find. Let's discuss and refine this point a bit, perhaps also get people from the chat to give their opinion There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Указал этот кейс для каких-то простых сценариев, которые могут возникнуть. Думаю можно написать дополнительно, что в целом идея смешения серверной логики и фронтовой в рамках одного проекта это плохая идея |
||
|
||
const App = ({ Component, pageProps }: AppProps) => { | ||
return ( | ||
<Provider1> | ||
<Provider2> | ||
<BaseLayout> | ||
<Component {...pageProps} /> | ||
</BaseLayout> | ||
</Provider2> | ||
</Provider1> | ||
); | ||
}; | ||
|
||
export default App; | ||
```tsx title="app/routes/get-example/route.ts" | ||
export { getExample as GET } from '@/pages/example'; | ||
``` | ||
Then you can import the `App` component and global project styles into `pages/_app.tsx` as follows: | ||
|
||
```tsx | ||
// pages/_app.tsx | ||
### Additional recommendations | ||
- Use the `api` segment in the `shared` layer 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, in a basic scenario this is the `api` segment in the `shared` layer. | ||
|
||
import 'app/styles/index.scss' | ||
## Legacy approach with Pages Router | ||
Page routers should be placed in the `pages` folder in the root of the project, similar to `app` for the App Router. | ||
The structure inside `src` where the layer folders are located remains unchanged. | ||
|
||
export { default } from 'app/providers'; | ||
```sh | ||
├── pages # Pages folder (Next.js) | ||
│ ├── _app.tsx | ||
│ ├── api | ||
│ │ └── example.ts # API Route re-export | ||
│ └── example | ||
│ └── index.tsx | ||
└── src | ||
├── app | ||
├── pages | ||
│ └── example | ||
│ ├── index.ts | ||
│ ├── ui | ||
│ │ └── example.tsx | ||
│ └── routes | ||
│ ├── config.ts # API Route config | ||
│ └── handler.ts # API Route | ||
├── widgets | ||
├── features | ||
├── entities | ||
└── shared | ||
``` | ||
|
||
## Dealing with App Router {#app-router} | ||
### Functionality re-export from the public API `src/app/index.ts` to `pages/_app.tsx` | ||
|
||
App Router has become stable in NextJS version 13.4. App Router allows you to use the `app` folder for routing instead of the `pages` folder. | ||
To comply with the principles of FSD, you should treat the NextJS `app` folder in the same way as recommended | ||
to resolve a conflict with the NextJS `pages` folder. | ||
```tsx title="pages/_app.tsx" | ||
export { App as default } from '@/app'; | ||
``` | ||
|
||
The approach is to move the NextJS `app` folder to the root folder of the project and import the FSD pages into the NextJS `app` folder. This saves | ||
the FSD project structure inside the `src` folder. You should still also add the `pages` folder to the root, because the App router is compatible with the Pages router. | ||
### Example of re-exporting a page from `src/pages/example` to `pages/example/index.tsx` | ||
|
||
```tsx title="pages/example/index.tsx" | ||
export { Example as default } from '@/pages/example'; | ||
``` | ||
├── app # NextJS app folder | ||
├── pages # Stub NextJS pages folder | ||
│ ├── README.md # Description of why this folder exists | ||
├── src | ||
│ ├── app # FSD app folder | ||
│ ├── entities | ||
│ ├── features | ||
│ ├── pages # FSD pages folder | ||
│ ├── shared | ||
│ ├── widgets | ||
``` | ||
|
||
[][ext-app-router-stackblitz] | ||
|
||
## Middleware | ||
### API Routes | ||
It is suggested to use a new `routes` segment in the `app` or `pages` layer to work with API Routes. | ||
|
||
If you are using middleware in a project, it also needs to be moved from `src` to the root of the project. Otherwise, NextJS simply won't see it — middleware must be located strictly at the root next to `app` or `pages`. | ||
```tsx title="app/api/example.ts" | ||
export { handler as default, config } from '@/pages/example'; | ||
``` | ||
|
||
## See also {#see-also} | ||
## See also | ||
|
||
- [(Thread) About the pages directory in NextJS](https://t.me/feature_sliced/3623) | ||
[Next.js Project Structure](https://Next.js.org/docs/app/getting-started/project-structure) | ||
[Next.js Page Layouts](https://Next.js.org/docs/app/getting-started/layouts-and-pages) | ||
|
||
[project-knowledge]: /docs/about/understanding/knowledge-types | ||
[ext-app-router-stackblitz]: https://stackblitz.com/edit/stackblitz-starters-aiez55?file=README.md | ||
GeorgKrom marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[ext-app-router-stackblitz]: https://stackblitz.com/edit/stackblitz-starters-aiez55?file=README.md |
Uh oh!
There was an error while loading. Please reload this page.