Nextを利用したWebサービス開発設計
最近Next.jsを使い始めました。
現在の、Nextを使ったサービス開発時の環境構築を行いましたのでメモしておきます。
基本的にはTypeScriptベースのcreate next-appで作成したディレクトリ構成を維持しつつ、testを導入したり、Sassを導入してディレクトリ設計を行いました。
ディレクトリ構成
Next導入時は、pages、public、stylesなどがデフォルトで用意されています。
若干いじってディレクトリ構成を行いましたが、私の環境は以下のような形にしました。
├── __tests__ # テストコード
├── components # Atomic Designに準拠
│ ├── atoms
│ │ └── Button
│ │ ├── index.tsx # コンポーネント
│ │ └── Button.module.scss # コンポーネントスタイル
│ ├── molecules
│ │ └── Menu
│ ├── organisms
│ │ ├── Header
│ │ └── Navbar
│ └── templates
│ ├── layout.tsx # layoutコンポーネント
│ └── layout.module.scss
├── api # APIに接続のために必要な全てのコード
├── utils # 共通ロジック、定数
├── context # React Context
├── hooks # カスタムhooks
├── types # 型定義ファイル
├── pages # ルーティング(NextJSのルールに準拠)
├── public # 静的ファイル(画像ファイルなど)
└── styles # 各コンポーネントで共通利用されるグローバルスタイル
Nextに依存した部分は公式ドキュメントをご確認ください。
今回は独自で行なったディレクトリ構成部分について紹介します。
components
Atomic Designに則ったディレクトリ構成を行なっています。
Nextでは、ページで再利用可能なLayoutsコンポーネントが用意されおり、layout.tsxにヘッダー、フッター、サイドバーなどページ共通で利用できるレイアウトを作成してpegeコンポーネントで共通利用します。
コンポーネントのスタイル要素は別ファイルに切り分け、コンポーネント別にフォルダを用意し、DOM要素とスタイル要素をセットで格納しています。
共通で利用されるスタイルはstyles/global.scssなどで定義します。
api
apiフォルダは、元々pages内にありますが、データとコンポーネントの役割を分けたいため、pagesと並列にしました。
すべてのAPI通信に必要なコードを管理するようにします。
api/apiUser.ts
export const fetchUser = async () => {
return await axios
.get('/user')
.then((res) => res.data)
.catch((error) => error)
}
export const createUser = async (params: typs) => {
return await axios
.post('/user', params)
.then((res) => res.data)
.catch((error) => error)
}
その他
hooksやcontextなどReactに依存したコードは専用のディレクトリを用意して管理を行うようにしました。
共通で利用されるロジックや、定数などはutils内で管理します。
データ管理
componentsには、取得先の異なる同フォーマットデータを受け取ることが想定されたので、APIはpagesからリクエストを行い、componentsはデータを受け取るだけにしておきます。
useSWR
データ取得用のhooksライブラリとしてuseSWRというものがあります。
まだ使いきれていないのですが、キャッシュを利用したデータ取得など、軽量にデータ通信を行うことができるようです。
いくつかのhooksが用意されており、シチュエーションに合わせて利用することができるようです。
hooksでAPIリクエストを行うことになるので、useSWRを利用する場合の設計はまた変わってきそうです。
さいごに
設計はなかなか公式の情報だけでは学べないので、OSSのソースを参考にしたり、記事を読んだりしましたが、結論人それぞれです。
フレームワークを使うことで、ある程度ルールを用意してもらったり、環境部分もフレームワークに任せることができて開発に専念することができるのが非常に大きなメリットです。
Discussion