Node.js >= 13
Visual Studio Code Extensions
> npm install
> npm run dev
master
Always represents the latest codes. It is being protected by the branch protection rules.
Releases
After heavily tested the master branch, tag and release using SemVer.
For more information creating branches, read the PAYW Contributing Guidelines.
Check out PAYW Contributing Guidelines
Next.js gracefully generates routes based on the files/directories structure inside the pages
. It is much easier to manage and visualize them and reduces overheads configuring the routes. You can write a page component just like the other normal React components.
However, when it comes to separating a large page component into multiple child components, you cannot put those child components inside the pages
directory because they're going to be considered as a page by Next.js.
pages
└─ home
└─ index.tsx # https://npoem.io/home
pages
└─ home
├─ index.tsx # https://npoem.io/home
└─ SearchBar.tsx # https://npoem.io/home/SearchBar
So eventually what you're going to do is put them inside components
.
components
└─ SearchBar.tsx
...
pages
└─ home
└─ index.tsx
What bad thing happen here is that they're not organized together even if they're strongly related and you have to keep moving around two directories.
So we're going to use a page component just like a bridge. Create a page component as extremely simple as possible making it needless to frequently visit again once it is created.
// src/pages/home/index.tsx
import { NextPage } from 'next'
import Home from '@/components/Home'
const Page: NextPage = () => {
return <Home /> // All the states and logics for this page are inside the `Home` component
}
export default Page
Share the same props type if a page receives some data from server side.
- import { NextPage } from 'next'
+ import { GetServerSideProps, NextPage } from 'next'
- import Home from '@/components/Home'
+ import Home, { HomeProps } from '@/components/Home'
- const Page: NextPage = () => {
+ const Page: NextPage<HomeProps> = (props) => {
- return <Home />
+ return <Home {...props} />
}
export default Page
+ export const getServerSideProps: GetServerSideProps<HomeProps> = async (props) => {
+ return {
+ props: {}
+ }
+ }
VSCode Snippet
We prepare a simple snippet for creating a new page component.
page
Basically components are structured like below.
components
└─ MyComponent
├─ index.tsx
└─ style.scss
The name index is automatically resolved and allows us to import the module through a directory name without writing full path including the index.tsx
.
import MyComponent from '@/components/MyComponent'
If a component doesn't include its own style and is a leaf component, you can name it directly.
components
└─ MyComponent.tsx
You may wonder why not name them same as the component name.
# Approach 1
components
└─ MyComponent
├─ index.tsx
└─ MyComponent.scss
# Or do something like this
# Approach 2
components
├─ MyComponent.tsx
├─ MyComponent.scss
├─ YourComponent.tsx
├─ YourComponent.scss
├─ TheirComponent.tsx
└─ TheirComponent.scss
With these approaches, duplicate names distract our vision which results in hardness to easily index what components are there. Also the Approach 2 doesn't even allow to nest child components into a component.
What is worse, in terms of refactoring, there are many namespaces you have to modify.
components
- ├─ MyComponent.tsx
+ ├─ OurComponent.tsx
- ├─ MyComponent.scss
+ └─ OurComponent.scss
- import './MyComponent.scss'
+ import './OurComponent.scss'
We strongly follow the principles of Single source of truth and DRY(Don't Repeat Yourself).
VSCode Snippets
Alongside a page snippet, we also prepare a snippet for creating a new React component.
comp
styl
If a component is composed of several child components and they're only used inside that component, put them under the parent's component.
components
└─ Parent
├─ index.tsx
├─ style.scss
├─ Child1
│ ├─ index.tsx
│ ├─ style.scss
│ └─ Child3
│ ├─ index.tsx
│ └─ style.scss
└─ Child2.tsx
If one of the child components are imported from the components other than its parent, it should not placed under the parent.
Class Name
Name the mostly outer element's class with component-{component-name}
.
For example,
const Home: React.FC = () => {
return <div className="component-home">...</div>
}
const SuperCharger: React.FC = () => {
return <div className="component-super-charger">...</div>
}
If a component specifically depends on a parent component, concatenate the component names.
components
└─ Library
├─ index.tsx
├─ style.scss
└─ Book
├─ index.tsx
└─ style.scss
const Library: React.FC = () => {
return <div className="component-library">...</div>
}
const Book: React.FC = () => {
return <div className="component-library-book">...</div>
}
In this way, we can create a unique stylesheet scope without using module feature of Next.js which append a randomly unique string to each class name.