ディレクトリ構成(monorepo, React, Next.js, TypeScript)
基本となるディレクトリ構成は、bulletproof-react をベースにする
ポイント
- src配下にコードをまとめる
- スコープをグローバルと機能別(features)で分ける
- features配下のpublic apiは、index.tsでまとめてそれ以外をprivateな扱いとする
以下引用
#
src
|
+— assets # assets folder can contain all the static files such as images, fonts, etc.
|
+— components # shared components used across the entire application
|
+— config # all the global configuration, env variables etc. get exported from here and used in the app
|
+— features # feature based modules
|
+— hooks # shared hooks used across the entire application
|
+— lib # re-exporting different libraries preconfigured for the application
|
+— providers # all of the application providers
|
+— routes # routes configuration
|
+— stores # global state stores
|
+— test # test utilities and mock server
|
+— types # base types used accross the application
|
+— utils # shared utility functions
src/features/awesome-feature
|
... 同上
|
+-- index.ts # entry point for the feature, it should serve as the public API of the given feature and exports everything that should be used outside the feature
monorepoでは、上述の上位レイヤーとしてapps、pacakgesを用意する。
※ turborepo/examples をベースにする
JavaScript/TypeScript 以外もmonorepoで管理している場合は、さらにその上位レイヤーとして言語別(Go、TypeScript…)で分けたり、プロジェクト別に分けたりなども必要。
apps # monorepoで管理したいアプリディレクトリ。例: appA、appB...
|
+— appA
|
+— appB
|
packages # publicには公開しないが、monorepo内で使用可能なprivateライブラリ
|
+— packageA
|
+— packageB
|
+— tsconfig # 複数アプリから参照されるconfigファイルなどもpackagesへ
[補足]
yarn workspacesでのmonorepo構築をする場合、rootのnode_modules配下にシンボリックリンクが作成される
※ turborepoでもyarn workspacesを使用している
node_modules/
|
+— appA
|
+— appB
|
+— packageA
|
+— packageB
src/routesに関しては、Next.jsの場合はsrc/pagesに置き換える。
デフォルトで、pages or src/pagesからルーティングを読み取ってくれるので、新たなconfigを作成する必要はない。
「packagesだけではなく、apps/appA/src/packagesも採用する」
monorepoでの管理コストについて
packagesの管理はprivateとはいえコストがかかる。
特にpackage.jsonでのバージョン管理にコストがかかる。
各種packageが依存しているライブラリについて、個別に管理する必要があるため。
packageA
|
+— package.json # 全ての依存モジュールとそのバージョンを指定する必要がある
この時バージョンの指定方法によっては、
appAからpackageAを参照した際に、同一ライブラリでバージョンが異なる場合など、
二種類のバージョンがインストールされ混在したりする。
package.jsonのresolutionsで依存パッケージのバージョンを固定
そのため下記の方針などがあると、管理コストを少し下げられる
- packagesの粒度を細かくしすぎない
- アプリ内に閉じた apps/appA/src/packages も作成する
- 将来的に複数から参照されるまではアプリ内に閉じる。
- 結局複数から参照されない場合などがあるため、まずはスコープを小さく。
features と packagesについて
役割が被ってくることがあるが、
上述のpackagesの粒度を細かくしすぎないという点では、
featuresを含んでいる扱いにするとよさそう。
packageA/src/features
とする。