📁 モノレポのファイル構造
複数のプロジェクトを1つの GitHub リポジトリで管理する際の推奨されるディレクトリ構造です。各プロジェクトは独立した Cloudflare Pages デプロイを持ちます。
monorepo-demo/
├── packages/
│ ├── landing/ ← ランディングページ
│ │ ├── index.html 📄 メインページ
│ │ ├── styles.css 🎨 スタイル
│ │ ├── script.js ⚙️ ロジック
│ │ └── images/ 🖼️ 画像資産
│ │
│ ├── blog/ ← ブログサイト
│ │ ├── index.html
│ │ ├── posts/
│ │ │ ├── post-1.html
│ │ │ └── post-2.html
│ │ ├── build.sh 🔨 ビルドスクリプト
│ │ └── package.json
│ │
│ ├── api/ ← バックエンド API
│ │ ├── functions/
│ │ │ ├── api/
│ │ │ │ ├── users.js
│ │ │ │ └── posts.js
│ │ │ └── middleware.js
│ │ └── package.json
│ │
│ └── shared/ ← 共有ユーティリティ
│ ├── utils.js
│ ├── constants.js
│ └── package.json
│
├── .github/
│ └── workflows/
│ └── deploy.yml 🚀 CI/CD ワークフロー
│
└── package.json 📦 ルートパッケージ設定
🔍 パス監視(Path Watch)の実装
各プロジェクトは独立したパス監視を設定することで、該当フォルダの変更時のみデプロイがトリガーされます。
📊 パス監視の設定テーブル
| プロジェクト |
Include Paths |
Exclude Paths |
| landing |
packages/landing/** |
*.test.js, node_modules/** |
| blog |
packages/blog/** |
node_modules/**, .git/** |
| api |
packages/api/** |
tests/**, *.test.js |
🔗 API 経由での設定コード
# ランディングページの設定
curl -X PATCH https://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects/monorepo-landing \
-H "Authorization: Bearer {api_token}" \
-d '{
"build_config": {
"path_includes": ["packages/landing/**"],
"path_excludes": ["*.test.js"]
}
}'
✅ パス監視の動作例
シナリオ 1: ランディングページ更新
git add packages/landing/index.html
git commit -m "Update landing page design"
git push origin main
✅ monorepo-landing がデプロイされます
❌ monorepo-blog と monorepo-api はスキップ(変更なし)
シナリオ 2: 複数プロジェクト同時更新
git add packages/landing/styles.css packages/blog/posts/new-post.html
git commit -m "Update landing and add blog post"
git push origin main
✅ monorepo-landing がデプロイされます
✅ monorepo-blog がデプロイされます
❌ monorepo-api はスキップ(変更なし)
シナリオ 3: 除外パスの変更
git add packages/api/src/utils.test.js
git commit -m "Add unit tests"
git push origin main
⏭️ monorepo-api はスキップされます
理由: *.test.js は Exclude paths に指定されているため
📦 共有コードの管理
packages/shared/utils.js
// 日付フォーマッター
export function formatDate(date) {
return new Date(date).toLocaleDateString('ja-JP');
}
// API ベース URL
export function getApiBaseUrl() {
return process.env.API_URL || 'https://api.example.com';
}
// トークン検証
export function validateToken(token, secret) {
return token === secret;
}
packages/landing/script.js(共有コード利用例)
import { formatDate, getApiBaseUrl } from '../shared/utils.js';
// API からデータ取得
fetch(`${getApiBaseUrl()}/greeting`)
.then(r => r.json())
.then(data => {
console.log('Server time:', formatDate(data.timestamp));
});
package.json(ワークスペース定義)
{
"name": "monorepo-demo",
"version": "1.0.0",
"workspaces": [
"packages/landing",
"packages/blog",
"packages/api",
"packages/shared"
],
"scripts": {
"build": "npm --workspaces run build",
"test": "npm --workspaces run test"
}
}