この記事は、ハシゴ Advent Calendar 2020の 2 日目の記事です。
昨日の「JAMStack で開発したプロダクトで使った技術スタックと pros/cons」に引き続き、JAMStack なプロダクトの話です。今日はプロダクトのディレクトリ構成を(ほぼ)全部晒して、それぞれどういうファイルなの?っていうのを解説していきます。
実プロダクトの全体のディレクトリ構成ってあんまり晒されることがないと思うので、誰かのお役に立てば幸いです 🙏
ディレクトリ構成
はい、どーん(すいません、不要なもの一部除外してます)。
$ tree -a -I "\.DS_Store|\.git|node_modules|dist|public_story|.cache|\.log|" -N -L 2
.
├── .cz-config.js
├── .env
├── .envs
│ ├── [app].[env].env
│ ├── ...
├── .eslintignore
├── .eslintrc.js
├── .github
│ ├── ISSUE_TEMPLATE
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows
├── .gitignore
├── .lighthouserc.js
├── .storybook
│ ├── main.js
│ ├── ...
├── .stylelintrc.json
├── CHANGELOG.md
├── README.md
├── amplify.yml
├── budget.json
├── config
│ ├── fukuoka.js
│ ├── index.js
│ └── kansai.js
├── contents
│ ├── privacy-policy.md
│ └── terms-of-service.md
├── gridsome.config.js
├── gridsome.server.js
├── package-lock.json
├── package.json
├── plugin
│ ├── fukuoka.server.js
│ └── kansai.server.js
├── purgecss.config.js
├── renovate.json
├── ship.config.js
├── src
│ ├── assets
│ ├── components
│ ├── index.html
│ ├── layouts
│ ├── lib
│ ├── main.css
│ ├── main.js
│ ├── mixins
│ ├── pages
│ ├── templates
│ └── vue-shims.d.ts
├── static
│ ├── assets
│ ├── ...
├── stories
│ ├── assets
│ └── organisms
├── tailwind.config.js
└── tsconfig.json
昨日の記事でも書きましたが、本プロダクトはKANSAI STARTUP NEWS、FUKUOKA STARTUP NEWSの 2 つを展開しており、これを 1 リポジトリで開発しているため、各所にfukuoka.xxx
、kansai.xxx
なファイルがあるのが少し特徴的かなと思います。
以下、必要そうなものを抜粋して説明を書いていきます。
.cz-config.js
cz のやつです。VS Code 拡張のknisterpeter.vscode-commitizen
からも読み込めるので、これでシュシュっと commit してます(CLI 苦手勢)。
.env, .envs
.env
が実際に使う env ファイルで、npm script で実際にサーバーを立ち上げる前にnpm-run-all
のrun-s
で.envs
配下のファイルを.env
にコピーして使っています。福岡用/関西用、local/stg/prod で 2*3 の 6 パターンです。
.github
actions は reviewdog、Lighthouse CI、chromatic、shipjs 用があります。reviewdog が PR でフック、Lighthouse CI が schedule でフック、chromatic が push でフック、shipjs が issues コメントでフックしています。
ship.js に関しては導入して結構楽なリリースフローが出来たので、後日詳しく書く予定です。
amplify.yml
特にコレといった処理はありませんが、master 以外では storybook の build をして、各環境下でも storybook が見れるようになっています。ちなみに、あまり有効活用はされていません。
version: 0.1
frontend:
phases:
...(略)...
postBuild:
commands:
- if [ "${AWS_BRANCH}" != "master" ]; then npm run build:sb; fi
...(略)...
config
各環境用の設定ファイル群です。アプリからは意識しなくて済むように、アプリ側からはindex.js
を読んでいて、index.js
内で環境変数で振り分けをしています。
contents
固定ページ内に表示させるやつの markdown です。もともとは普通に vue ファイルとして書いてたんですが、単純にマークアップしすぎで見通しが悪かったので、リニューアルに伴って markdown に差し替えました。
福岡と関西で表示内容(主にサイト名)が異なるので、markdown 内に変換用の文字列を埋め込んであって、ページで parse する時にそれを置換しています。
plugin
本プロダクトは、ページの生成などは基本的に全てgridsome.server.js
内でやるようにしています。理由としては、context として変数を埋め込んだりとか、まぁ色々やらないといけなかったからなんですが、福岡と関西とそれぞれ独自に書きたい処理を plugin 配下のファイルに書いています。
具体的には、「関西だけ必要なページ」あるいは「福岡だけ必要なページ」をここに書いています。どちらを読み込むかは上述した config 内に埋め込んでいて、それをgridsome.config.js
経由で実行しています。
src
ここに関してはほぼデフォルトのディレクトリ構成を踏襲しています。components 配下は atoms、molecules、organisms の所謂 Atomic Design でとっていて、TOP レベルに全体を括っている Container を露出させています。これはまぁ、気分です。
$ tree src/components/ -L 1
src/components/
├── Container.vue
├── atoms
├── molecules
└── organisms
ただ前述した通り、ページはほぼgridsome.server.js
で作っているので、pages
配下ではなく、template
配下に持っていて、ページを作る時にそれぞれのtemplate
を当てています。
mixins の中には、各ページの meta 設定用の雛形ファイルと、GraphQL からのデータを使いやすいようによしなにする変換層のファイルがあります。
stories
storybook 本体が置いてあるんですが、諸事情で organisms 単位でしか作っていません。理由としては chromatic の free プランの制限が結構キツく(切実…)、あんまり多く書いてもリグレッションテストにかけられないからという感じですね…。かなしい。ただ減らしても減らしても結構キツいという現実もあります。
おわりに
全体を通して見ると、福岡/関西の振り分けを除けば、あまり特異なことはやっておらず、わりかしオーソドックスな構成だと思います。振り分けに関しては、また別途記事を書く予定なので、詳しくはそこでお伝えできればと思います:)