'Is this Next.JS folder structure recommended?

We have resorted to this following project structure

|- pages
    |- <page_name>
        |- index.js             # To do a default export of the main component
        |- MainComponent.jsx    # Contains other subcomponents
        |- main-component.css   # CSS for the main component
        |- OtherComponents.jsx  # more than 1 file for child components that are used only in that page
        |- __tests__            # Jest unit and snapshot tests
|- components
    |- index.js                 # Exports all the default components of each component as named exports
    |- CommonCmpnt1
        |- CommonCmpnt1.jsx
        |- common-cmpnt-1.css
        |- index.js             # To default export the component
        |- __tests__
    |- CommonCmpnt2
        |- CommonCmpnt2.jsx
        |- common-cmpnt-2.css
        |- index.js             # To default export the component
        |- __tests__

To clarify, nothing has broken and it works amazingly well. We have components that are reused in multiple pages inside the components directory, where we import as follows

// Assuming we are inside MainComponent.jsx
// ...
import { CommonCmpnt1 } from '../../components';    // We even take it a step further and use absolute imports

Also, components that are used only once reside side-by-side in it's pages folder.

The only problem we face now is the Hot Module reloading is broken, i.e. whenever we edit the .jsx file inside either the pages or the components directory, we have to manually reload the page to see effected changes (It doesn't affect the CSS files). It is something that we've grown accustomed to and so doesn't affect us seriously.

My question is, is there any impending catastrophe that we do not know of?



Solution 1:[1]

To all who are still interested in this, I personally recommend this approach due to the fact that it helps compartmentalize resources and allows for quickly finding things and unit testing.

It was inspired by an article by HackerNoon on How to structure your React app

Solution 2:[2]

Stumbled upon this post while searching for a suitable folder structure for NextJS myself. I've been using a similar structure but recently found that this is not how you're suppose to use NextJS.

I don't know too much about the details, but NextJS has optimizations at the page level. When you build a NextJS project, you will see the pages logged as part of the build. NextJS treats every component file under the pages folder as a page, so by placing non-page components in the pages folder, you are drastically increasing build time because now NextJS goes and builds every one of those components as a page.

Solution 3:[3]

I like the structure proposed in this article

https://medium.com/@pablo.delvalle.cr/an-opinionated-basic-next-js-files-and-directories-structure-88fefa2aa759

/root
  \_ /.next/
  \_ /components/
      \_ Button/
          \_ button.spec.jsx
          \_ button.styles.jsx
          \_ index.jsx
  \_ /constants/
      \_ theme.js
      \_ page.js
  \_ /contexts/
      \_ Locale/
         \_ index.js
      \_ Page/
         \_ index.js
  \_ /pages/
      \_ _app.jsx
      \_ _document.jsx
      \_ about.jsx
      \_ index.jsx
  \_ /providers/
      \_ Locale/
         \_ index.js
      \_ Page/
         \_ index.js
  \_ /public/
      \_ favicon.ico
      \_ header.png
  \_ /redux/
      \_ actions/
         \_ users/
            \_ index.js
         \_ products/
            \_ index.js
      \_ reducers/
         \_ users/
            \_ index.js
         \_ products/
            \_ index.js
      \_ store/
         \_ index.js
      \_ types/
         \_ index.js
  \_ /shared/
      \_ jsons/
          \_ users.json
      \_ libs/
          \_ locale.js
      \_ styles/
          \_ global.css
  \_ /widgets/
      \_ PageHeader/
          \_ index.jsx
  \
  \_ .eslintignore
  \_ .eslintrc
  \_ .env
  \_ babel.config.js
  \_ Dockerfile
  \_ jest.config.js
  \_ next.config.js
  \_ package.json
  \_ README.md

Solution 4:[4]

If someone is still interested, I save the file depending on its type in my project, for example:

|-Nextjs-root
  |-Components
    |-Header.js
    |-Footer.js
    |-MoreExamples.js
  |-styles
   |-globals.css
   |-header.module.css
   |-footer.module.css
  |-Services
    |-api              #Axios config to connect to my api
  |-Context
   |-AuthContext.js    #Global context to my app for auth purposes
  |-pages
   |-index.js

Solution 5:[5]

Here is what I recommend, using a modular design pattern:

/public
    favicon.ico
/src
    /common
        /components
            /elements
                /[Name]
                    [Name].tsx
                    [Name].test.ts
        /hooks
        /types
        /utils
    /modules
        /auth
            /api
                AuthAPI.js
                AuthAPI.test.js
            /components
                AuthForm.tsx
                AuthForm.test.ts
            auth.js
    /pages
        /api
          /authAPI
              authAPI.js
          /[Name]API
              [Name]API.js
        _app.tsx
        _document.tsx
        index.tsx

I wrote an article about it: https://dev.to/vadorequest/a-2021-guide-about-structuring-your-next-js-project-in-a-flexible-and-efficient-way-472

The only thing you must really be careful about is to not have anything under pages that aren't actual pages or API endpoints (e.g: tests, components, etc.), because there is no way to ignore them and Next will bundle and deploy them as actual pages.

Solution 6:[6]

The way that now suit me most is to use the pages folder only for routing purpose, components in each file is just a wrapper for the "real" page components in src folder. With this approach I can structure my homepage more easily and it feel more intuitive - to contain the layout and its child components at the same folder.

Solution 7:[7]

Make sure to separate backend-only files from frontend + backend files

Regardless of what you name them, I would recommend having two directories with very clear semantics:

  • the backend-only directory: can make backend-only operations, e.g. direct DB or filesystem accesses (require('fs'))
  • the frontend + backend directory: frontend safe things only. Since Next.js is an SSR setup, anything that is frontend safe also has to be backend safe, so you can also use them from the backend, e.g. shared configs or helpers.

This is important because otherwise you will start to hit errors such as:

Module not found: Can't resolve 'fs'

when factoring things out with HoCs, and as mentioned at Module not found: Can't resolve 'fs' in Next.js application I do not know how to solve this except by making this clear and definite split.

Perhaps this is the intended semantic of the lib/ vs components/ convention commonly used, but I couldn't find a clear quote.

I'm more tempted to just call them back/ and front/

ESLint pages/, components/, and lib/ by default

This is the only clear in-upstream-code effect of components/ and lib/ that I could find as mentioned at: https://nextjs.org/docs/basic-features/eslint#linting-custom-directories-and-files (pages/ of course is magic and contains the URL entry points, and you should obviously not put anything else there):

By default, Next.js will run ESLint for all files in the pages/, components/, and lib/ directories.

It doesn't matter much in that case as the directory list can be easily configured as documented there.

Solution 8:[8]

There no a correct way to define your struture. This is how i defined

  • src
    • components
      • layout.js --- component inside components folder, more than one page will use this component
      • templates --- components to a specific page
        • home -- homePage
          • article.js -- Article Component
      • ui --- styled components, ex: Button, Title, Link
    • pages
    • styles
  • public