(仮) NextJS モノレポ運用
これは ランサーズ Advent Calendar 2021 4 日目の記事です。
個人の開発では1レポジトリで完結するようなプロジェクトをよく作成します。
ただし実際の事業はスケールしたり、プロジェクトの中でも他のプロジェクトにも共有したいリソースというのは出るものなので初期段階でもしっかりとした基盤を事前に用意したいと思ったので作成しました。
プロジェクト構成
- ルートプロジェクト: syonet_eight
上記のようなルートプロジェクトにサブプロジェクトを git submodule
で分割して管理しているような構成にしてます。
基本はGitなので対象のサブプロジェクト同士で異なるブランチでの検証も可能だったりします。
一部 git submodule
管理されていないサブプロジェクトもありますが。
次にそれぞれのプロジェクトの説明に入ります。
syonet_eight
ルートプロジェクト:サブプロジェクトよりも上の階層にある大元のプロジェクトになります。
yarn workspace
NodeJSのライブラリをルートプロジェクトに集中管理し、 yarn workspace
によるモノレポな環境にしています。
ルートプロジェクトにライブラリ管理を集中化させてしまってますが、サブプロジェクト側のpackage.jsonにバージョンの異なるライブラリを管理させたり、部分的に使用したいライブラリの管理ができるようになっているんじゃないかなと思います。
npm scripts
などもルートプロジェクトで管理するようにしてますので基本、CLIのカレントはルートプロジェクトのままで作業することになります。
VSCodeの設定の共有化
.vscodeをルートプロジェクトに置くことでサブプロジェクトでも自動にVSCodeの設定が適応されます。
以下設置しているファイルを箇条書きで説明します。
-
extensions.json
使用するVSCode拡張の共有
VSCodeを開いたときに推奨の拡張とかサジェストの表記がされるようになると思います。 -
launch.json
デバッグの設定を記載
プロジェクトごとのリモートデバッグによるポートの専有とか防げるんじゃないでしょうか。 -
settings.json
エディターの設定
ESLintの有効化や保存時のフォーマッタ設定
その他モラル的な基本設定とか入れればいいんじゃないでしょうか。 -
xxxxx.code-snippets
プロジェクトまたがってコピペ的に使いたいの記載すればいいんじゃないでしょうか。
Storybookの展開
プロジェクトをまたがった設定についてこちらになります。
yarn storybook
によりコンポーネントのカタログのようなものを閲覧できます。
サブプロジェクトにある xxx.stories.mdx
を元に作成されます。
軽くコンポーネントのPropsの検証ができたり
使用しているタグなど実装に関してのアクセシビリティが適切そうかチェックしたり
レンダリングのパフォーマンス確認などできるようにしています
CIのスケジュールによる全プロジェクトのUT実行
設定についてこちら
それぞれのサブプロジェクトの最新のmasterブランチを持ってきてlint, jestによるテスト実行をするようにしてます。
サブプロジェクト側でも個別にGitHub Actionsによるワークフローを記載しているのでそれぞれのレポジトリのプッシュでもテスト実行するようにしています。
syonet_eight_www
サブプロジェクト:NextJSによるプロジェクトになります。
Serverless Next.js Componentによるデプロイ
NextJSの本家Vercel でもいいんですけどAWSにデプロイ可能なServerless Frameworkを採用しています。
デプロイの仕組みの説明難しいですが serverless.yml の情報がAWSのCloudFormationのテンプレートとして展開されてAWSのそれぞれのサービスをよしなに使って1つのWebサービスを作ってしまうというものです。
下記の図はデプロイで反映するAWSのサービスのイメージになります。
それぞれのAWSのサービスが外部のユーザから見てどう使われているのかのイメージを記載すると
なのをServerless Next.js Componentで再現できちゃうらしいです。
SPA想定だったReactの資産をフル活用できますね。
syonet_eight_design_system
サブプロジェクト:共通のデザインなどをまとめるプロジェクトです。
共通コンポーネントをライブラリ化
yarn build:design_system
を実行することでライブラリ化します。
ルートプロジェクトのpackage.jsonにある
"syonet_eight_design_system": "file:./projects/syonet_eight_design_system"
という指定により別のサブプロジェクトでも
import * as DesignSystem from 'syonet_eight_design_system';
で共通のコンポーネントを使用することが可能です。
Figmaで作成したパーツのインポート
yarn import:figma
でFigmaで作成したものをインポートするような仕組みを作ってます。
実装したコードはこちらです
SVG化して使うのは結構安易そうですが、DOMとして扱うのは難しめにみてます。
(だってあいつらNodeIDの順番とか位置関係ようわからんし)
ビルドの設定NextJSのをそのままつかってる
tsconfig.jsonとか.babelrcの設定はNextJSで動かしていたものを使用してます。
syonet_eight_www & syonet_eight_design_system 共通の取り組み
ビジュアルリグレッションテスト実施
reg-suitというGitのプッシュを実行した際にコンポーネントの差分をビジュアライズする仕組みを入れてます。
例えばこんな差分があったときに
差分としての検知として
一覧が表示されて詳細をみようとすると
どのへんに差分があるのかというのをビジュアライズしてくれます。
CIの設定としてこちらになります。
GitHub Actions上では日本語フォントがないので fonts-noto
をインストールする必要があったりします。
あとはこちらのテストの結果は現状Slackで通知がくることを確認しています。
CSS in JSとしてemotion採用
好みですが、
import { css } from '@emotion/react';
でCSS ModulesぽくもpropsでCSSの値指定できるようないいとこ取りな書き方よくないっすか?
syonet_eight_storybook
サブプロジェクト:Storybookを配布するようにserverless.ymlしか置いてないです。
これもServerless Frameworkのコンポーネントをつかっており、websiteというものを使っています。
ただのSPAのサイトをホスティングしたい用途で使うのがちょうど良さそうです。
おわりに
以上自分なりのモノレポ運用についての記載でした。
まだ実装そのものを着手してなく、APIのプロジェクトも作成していない状況なのでこれからすすめていきたいと思います。
アドベントカレンダー、明日は @yuta-ron さんです。
よろしくおねがいします。
Discussion