iTranslated by AI
Architecture and Design for Web Service Development with Next.js
I recently started using Next.js.
I have set up the development environment for a web service using Next, so I'm documenting it here.
Basically, while maintaining the directory structure created by the TypeScript-based create next-app, I introduced test and Sass to design the directory structure.
Directory Structure
By default, Next provides folders like pages, public, and styles.
I have customized the directory structure slightly, and my environment looks like this:
├── __tests__ # Test code
├── components # Compliant with Atomic Design
│ ├── atoms
│ │ └── Button
│ │ ├── index.tsx # Component
│ │ └── Button.module.scss # Component style
│ ├── molecules
│ │ └── Menu
│ ├── organisms
│ │ ├── Header
│ │ └── Navbar
│ └── templates
│ ├── layout.tsx # Layout component
│ └── layout.module.scss
├── api # All code necessary for API connections
├── utils # Shared logic and constants
├── context # React Context
├── hooks # Custom hooks
├── types # Type definition files
├── pages # Routing (Compliant with Next.js rules)
├── public # Static files (images, etc.)
└── styles # Global styles shared across components
Please refer to the official documentation for parts dependent on Next.
This time, I will introduce the parts of the directory structure that I implemented uniquely.
components
The directory structure follows Atomic Design principles.
Next provides a reusable Layouts component for pages; I create layouts that can be used across pages (such as headers, footers, and sidebars) in layout.tsx and reuse them in page components.
Component style elements are separated into different files, and a folder is prepared for each component to store DOM elements and style elements as a set.
Styles used globally are defined in places like styles/global.scss.
api
The api folder is originally located inside pages, but since I want to separate the roles of data and components, I placed it parallel to pages.
I will manage all the code required for API communication here.
api/apiUser.ts
export const fetchUser = async () => {
// fetch user data
return await axios
.get('/user')
.then((res) => res.data)
.catch((error) => error)
}
export const createUser = async (params: typs) => {
// create a user
return await axios
.post('/user', params)
.then((res) => res.data)
.catch((error) => error)
}
Others
For code that depends on React, such as hooks and context, I have prepared dedicated directories to manage them.
Shared logic, constants, etc., are managed within utils.
Data Management
Since I expected components to receive data in the same format from different sources, I make API requests from pages and keep components responsible only for receiving the data.
useSWR
There is a library called useSWR which is a hooks library for data fetching.
I haven't fully mastered it yet, but it seems to allow for lightweight data communication, such as fetching data using cache.
It provides several hooks that can be used according to the situation.
Since API requests would be made using hooks, the design when using useSWR would likely change again.
In Conclusion
Design is something that's difficult to learn from official information alone, so I referred to OSS source code and read various articles, but the conclusion is that it varies from person to person.
By using a framework, you get some rules provided for you, and you can leave the environment setup to the framework, which is a huge benefit as it allows you to focus on development.
Discussion