TypeScript Monorepo 設定
Monorepo は複数のプロジェクトを同じコードリポジトリに置く開発モードです。
TypeScript はプロジェクト参照とツールチェーンを通じて Monorepo をサポートし、複数のパッケージを効率的に管理できます。
SVG 図: Monorepo 構造
なぜ Monorepo が必要か
プロジェクトに複数のパッケージ(ツールライブラリ、コンポーネントライブラリ、アプリケーションなど)が含まれる場合、従来の方法では複数のコードリポジトリを保守する必要があります。
Monorepo はすべてのパッケージを同じリポジトリに置くため、コード共有がより便利になり、バージョン管理がより統一されます。
TypeScript のプロジェクト参照機能により、Monorepo プロジェクトの型チェックとビルドがより効率的になります。
概念:Monorepo(単一リポジトリ)は複数の関連プロジェクトを同じコードリポジトリに置き、コード共有と協調開発を容易にします。
pnpm Workspace
pnpm はモダンなパッケージマネージャーで、Workspace 機能をネイティブにサポートしています。
ルートディレクトリ package.json
"name": "my-monorepo",
"version": "1.0.0",
"private": true,
// pnpm workspace を有効化
"packages": [
"packages/*"
],
// 開発依存関係
"devDependencies": {
"typescript": "^5.0.0"
},
// スクリプト
"scripts": {
"build": "pnpm -r run build",
"clean": "pnpm -r run clean",
"type-check": "pnpm -r run type-check"
}
}
pnpm:pnpm の Workspace 機能は、packages ディレクトリ内のパッケージを自動的にリンクできます。
プロジェクト構造
Monorepo プロジェクトのディレクトリ構造を作成します。
ディレクトリ構造
├── packages/
│ ├── utils/# ツールパッケージ
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ │
│ ├── ui-components/# UI コンポーネントパッケージ
│ │ ├── src/
│ │ │ ├── Button.tsx
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ │
│ └── app/# アプリケーション
│ ├── src/
│ │ └── index.tsx
│ ├── package.json
│ └── tsconfig.json
│
├── package.json# ルートディレクトリ設定
├── tsconfig.base.json# 基本設定
└── pnpm-workspace.yaml# pnpm 設定
packages:すべてのパッケージは packages ディレクトリの下に配置され、各パッケージは独立した package.json と tsconfig.json を持ちます。
基本的なTypeScript設定
すべてのパッケージが使用する基本設定を作成します。
tsconfig.base.json
// コンパイラオプション
"compilerOptions": {
// ターゲットバージョン
"target": "ES2020",
// モジュールシステム
"module": "ESNext",
// 厳密モード
"strict": true,
// ライブラリの型チェックをスキップ
"skipLibCheck": true,
// ES モジュールの相互運用を有効化
"esModuleInterop": true,
// ファイル名の大文字小文字の一致を強制
"forceConsistentCasingInFileNames": true,
// モジュール解決
"moduleResolution": "bundler",
// JSON モジュールを解析
"resolveJsonModule": true,
// モジュールを分離
"isolatedModules": true,
// 出力ファイルを生成しない
"noEmit": true
}
}
継承:各パッケージの tsconfig.json は基本設定を継承し、カスタマイズが必要なオプションのみを上書きします。
ツールパッケージ設定
ツールパッケージ用に TypeScript を設定します。
packages/utils/tsconfig.json
// 基本設定を継承
"extends": "../../tsconfig.base.json",
// コンパイラオプション
"compilerOptions": {
// 出力ディレクトリ
"outDir": "./dist",
// 宣言ファイルディレクトリ
"declarationDir": "./dist/types",
// 宣言ファイルを生成
"declaration": true,
// エントリファイルの宣言を生成
"declarationMap": true,
// モジュールのエクスポート方法
"module": "ESNext",
// プロジェクト参照を有効化
"composite": true
},
// 含めるファイル
"include": ["src/**/*"],
// 除外するファイル
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
composite:プロジェクト参照を有効にすると、TypeScript はこのパッケージをインクリメンタルコンパイルできます。
アプリケーション設定
メインアプリケーション用に TypeScript を設定し、他のパッケージを参照します。
packages/app/tsconfig.json
// 基本設定を継承
"extends": "../../tsconfig.base.json",
// コンパイラオプション
"compilerOptions": {
// 出力ディレクトリ
"outDir": "./dist",
// JSX 設定
"jsx": "react-jsx",
// パスエイリアス
"baseUrl": ".",
"paths": {
"@my-utils/*": ["../utils/src/*"],
"@my-ui/*": ["../ui-components/src/*"]
}
},
// プロジェクト参照
"references": [
{ "path": "../utils" },
{ "path": "../ui-components" }
],
// 含めるファイル
"include": ["src/**/*"],
// 除外するファイル
"exclude": ["node_modules", "dist"]
}
パスエイリアス:パスエイリアスを設定すると、同じリポジトリ内の他のパッケージを直接参照できます。
パッケージ間の依存関係
package.json で同じリポジトリ内のパッケージへの依存関係を宣言します。
packages/app/package.json
"name": "@my-org/app",
"version": "1.0.0",
"private": true,
"dependencies": {
// 同じリポジトリのパッケージを参照
"@my-org/utils": "workspace:*",
"@my-org/ui-components": "workspace:*",
// 外部依存関係
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
// 開発依存関係
"@types/react": "^18.2.0",
"typescript": "^5.0.0"
}
}
workspace:workspace:* を使用して同じリポジトリ内の他のパッケージを指定すると、pnpm が自動的に解決します。
ビルドスクリプト
Monorepo 用に統一されたビルドスクリプトを作成します。
ルートディレクトリ package.json
"scripts": {
// すべてのパッケージをビルド
"build": "pnpm -r run build",
// すべてのビルド成果物をクリーンアップ
"clean": "pnpm -r run clean",
// 型チェック
"type-check": "pnpm -r run type-check",
// すべてのパッケージをテスト
"test": "pnpm -r run test",
// インクリメンタルビルド
"build:watch": "pnpm -r --parallel run build:watch",
// アプリケーションを起動
"dev": "pnpm --filter @my-org/app run dev"
}
}
pnpm -r:すべてのパッケージの同名スクリプトを再帰的に実行します。
注意事項
- パッケージ命名規則:@org-name/package 形式を使用
- 独立したバージョン:各パッケージは独立してバージョン管理できます
- workspace プロトコル:workspace:* を使用して同じリポジトリのパッケージを参照
- ビルド順序:依存されるパッケージを先にビルドする必要があります
ベストプラクティス:Monorepo は複数の関連プロジェクトの管理に適しており、コードの再利用と開発効率を大幅に向上できます。
まとめ
Monorepo はモダンなフロントエンドプロジェクト管理の推奨モードです。
- pnpm Workspace:Monorepo をネイティブサポート
- プロジェクト参照:インクリメンタルコンパイルを実現
- パスエイリアス:同じリポジトリのパッケージを簡単に参照
- 一元管理:設定と依存関係を共有
その他の拡張推奨:プロジェクトに複数の関連パッケージが含まれる場合は、Monorepo 方式を優先的に検討してください。