Go+Next.jsの構成で設計を考えてボイラープレートを組んだよ
木瓜丸です。
最近こんなツイートを見かけました。
木瓜丸「ただしい😐」
そこで、最近Go+Next.js(+PostgreSQLとかS3とか)みたいな構成でWebアプリの個人開発をやっているので、その構成で良く使う部分をまるごとボイラープレート化して公開してみることにしました。
この記事では取り急ぎ、実装上の思想や意識している点をまとめておきたいと思います。よかったらアドバイスとか下さい。Forkして使って頂くのも大歓迎です!
※本記事ではデプロイの話はしません。
概要
本ボイラープレートでは、ユーザーのメール認証、ユーザー登録、ログイン、セッション管理、設定変更といった、ユーザー管理を伴うアプリケーションでは頻繁に実装する必要がある機能をあらかじめ実装しています。APIの設計はDDDに従い、フロントエンドでのコンポーネント管理にはAtomic Designを採用しています。
構成
API
- Go
- DB: PostgreSQL
- Object Storage: AWS S3 (ローカル環境ではminioを採用)
- SMTP: Gmail
画像などの保存にはS3を使用します。アップロードにはAWS S3互換のストレージで提供されているPresigned URLを使用します。
また、メール認証に用いるメールサーバーはGmailを利用します。
フロントエンド
- Next.js(TypeScript)
- sass-loader
スタイリングにはSCSS moduleを使用します。スタイリングがめんどくさい時にはフレームワークなどを採用して適宜導入して下さい。
全体のディレクトリ構成
.
├── Makefile
├── docker-compose.yml
├── README.md
├── api/
│ ├── cmd/
│ ├── internal/
│ ├── migrations/
│ ├── Dockerfile
│ ├── README.md
│ ├── go.mod
│ └── go.sum
├── data/
│ └── minio/
└── front/
├── components/
├── hooks/
├── libs/
├── pages/
├── public/
├── styles/
├── types/
├── README.md
├── next.config.js
├── package-lock.json
├── package.json
├── tsconfig.json
└── yarn.lock
フロントエンドとDockerを起動するコマンドをMakeで作ってあります。DBのマイグレーションもMakeに書いてあります。
API
ディレクトリ構成はStandard Go Project Layoutを参考にしています。
DBのORMにはgormを採用し、マイグレーションは別途golang-migrateを採用しました。
全体的な設計思想としてはDDDを意識しており、api/cmd/main.goにて依存の注入を手動で行っています。
.
├── Dockerfile
├── README.md
├── cmd
│ └── main.go
├── go.mod
├── go.sum
├── internal
│ ├── adapters
│ ├── controllers
│ ├── entities
│ ├── errors
│ ├── infrastructures
│ ├── middlewares
│ └── usecases
└── migrations
├── 20221123153221_create_users_table.down.sql
├── 20221123153221_create_users_table.up.sql
├── 20221123153312_create_email_verifications_table.down.sql
└── 20221123153312_create_email_verifications_table.up.sql
リクエストの流れとしては以下の通りです。
Controller (internal/controllersパッケージ)
↓
Usecase (internal/usecasesパッケージ)
↓
Entities (internal/entitiesパッケージ)
また、internal/adaptersパッケージでは外部サービス(GmailとS3)を扱うためのインターフェースが定義されています。internal/entitiesやinternal/adaptersで定義されたインターフェースはinternal/infrastructuresで実装され、cmd/main.goで注入されます。
フロントエンド
コンポーネント管理
コンポーネントの管理はAtomic Designに従いました。コンポーネント粒度の目安は以下の通りです。
Pages
APIとの通信やページ全体の状態を保持し、Template以下の粒度のコンポーネントに注入する役割を担います。
Template
Orgzanizations以下の粒度のコンポーネントを子に持ち、全体のデザインを定めます。
この時、表示にあたり必要なデータを状態として保持しません。(表示/非表示くらいはギリおkかなーと思うけど、それが全体のロジックに関係するならPagesから注入するべき)
Organizations
AtomsとMoleculesを組み合わせてレイアウトしたものです。
Organizationsより細かいコンポーネントではビジネスロジックにかかわる機能を持ってはいけません。
Molecules
AtomsやAtomsレベルの要素を組み合わせたものです。Molecules以下の粒度では使い回しを大前提として作成します。よって汎用性の高さが一つの切り出しの基準になります。
Atoms
ボタンや単一のテキスト、単体のフォームなどです。デザインツールで一つの箱で表現するくらいがAtomsにあたるかなと思います。
状態管理
以前記事にした状態管理手法を採用しています。よかったら見ていってください。
おわりに
ざっくり構成や設計思想をまとめてみました。詳細はコードを参照して頂けると嬉しいです。
コメント等もお待ちしています!
Discussion