monorepo-management
Turborepo、Nx、pnpm workspacesを活用したモノレポ管理をマスターし、最適化されたビルドと依存関係管理を備えた効率的でスケーラブルなマルチパッケージリポジトリを構築します。モノレポのセットアップ、ビルドの最適化、共有依存関係の管理が必要な場面で活用してください。
description の原文を見る
Master monorepo management with Turborepo, Nx, and pnpm workspaces to build efficient, scalable multi-package repositories with optimized builds and dependency management. Use when setting up monorepos, optimizing builds, or managing shared dependencies.
SKILL.md 本文
モノレポ管理
複数のパッケージとアプリケーション全体でコード共有、一貫したツーリング、アトミックな変更を可能にする効率的でスケーラブルなモノレポを構築します。
このスキルをいつ使うか
- 新しいモノレポプロジェクトのセットアップ
- マルチリポからモノレポへの移行
- ビルドとテストのパフォーマンス最適化
- 共有依存関係の管理
- コード共有戦略の実装
- モノレポの CI/CD セットアップ
- パッケージのバージョニングと公開
- モノレポ固有の問題のデバッグ
コアコンセプト
1. モノレポが必要な理由
利点:
- コードと依存関係の共有
- プロジェクト全体にわたるアトミックなコミット
- 一貫したツーリングと標準
- リファクタリングが容易
- 依存関係管理の簡素化
- コード可視性の向上
課題:
- スケール時のビルドパフォーマンス
- CI/CD の複雑性
- アクセス制御
- 大規模な Git リポジトリ
2. モノレポツール
パッケージマネージャー:
- pnpm workspaces (推奨)
- npm workspaces
- Yarn workspaces
ビルドシステム:
- Turborepo (ほとんどの場合に推奨)
- Nx (機能豊富、複雑)
- Lerna (古い、メンテナンスモード)
Turborepo セットアップ
初期セットアップ
# 新しいモノレポを作成
npx create-turbo@latest my-monorepo
cd my-monorepo
# 構造:
# apps/
# web/ - Next.js アプリ
# docs/ - ドキュメントサイト
# packages/
# ui/ - 共有 UI コンポーネント
# config/ - 共有設定
# tsconfig/ - 共有 TypeScript 設定
# turbo.json - Turborepo 設定
# package.json - ルート package.json
設定
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
},
"type-check": {
"dependsOn": ["^build"],
"outputs": []
}
}
}
// package.json (ルート)
{
"name": "my-monorepo",
"private": true,
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"test": "turbo run test",
"lint": "turbo run lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"clean": "turbo run clean && rm -rf node_modules"
},
"devDependencies": {
"turbo": "^1.10.0",
"prettier": "^3.0.0",
"typescript": "^5.0.0"
},
"packageManager": "pnpm@8.0.0"
}
パッケージ構造
// packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.0.0",
"private": true,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./button": {
"import": "./dist/button.js",
"types": "./dist/button.d.ts"
}
},
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts",
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
"lint": "eslint src/",
"type-check": "tsc --noEmit"
},
"devDependencies": {
"@repo/tsconfig": "workspace:*",
"tsup": "^7.0.0",
"typescript": "^5.0.0"
},
"dependencies": {
"react": "^18.2.0"
}
}
pnpm Workspaces
セットアップ
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
- "tools/*"
// .npmrc
# 共有依存関係のホイスト
shamefully-hoist=true
# 厳密なピア依存関係
auto-install-peers=true
strict-peer-dependencies=true
# パフォーマンス
store-dir=~/.pnpm-store
依存関係管理
# 特定パッケージに依存関係をインストール
pnpm add react --filter @repo/ui
pnpm add -D typescript --filter @repo/ui
# ワークスペース依存関係をインストール
pnpm add @repo/ui --filter web
# すべてのパッケージにインストール
pnpm add -D eslint -w
# すべての依存関係を更新
pnpm update -r
# 依存関係を削除
pnpm remove react --filter @repo/ui
スクリプト
# 特定パッケージでスクリプトを実行
pnpm --filter web dev
pnpm --filter @repo/ui build
# すべてのパッケージで実行
pnpm -r build
pnpm -r test
# 並行実行
pnpm -r --parallel dev
# パターンでフィルタ
pnpm --filter "@repo/*" build
pnpm --filter "...web" build # web と依存関係をビルド
Nx モノレポ
セットアップ
# Nx モノレポを作成
npx create-nx-workspace@latest my-org
# アプリケーションを生成
nx generate @nx/react:app my-app
nx generate @nx/next:app my-next-app
# ライブラリを生成
nx generate @nx/react:lib ui-components
nx generate @nx/js:lib utils
設定
// nx.json
{
"extends": "nx/presets/npm.json",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"],
"cache": true
},
"test": {
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
"cache": true
},
"lint": {
"inputs": ["default", "{workspaceRoot}/.eslintrc.json"],
"cache": true
}
},
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": [
"default",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/tsconfig.spec.json"
],
"sharedGlobals": []
}
}
タスクの実行
# 特定プロジェクトのタスクを実行
nx build my-app
nx test ui-components
nx lint utils
# 影響を受けたプロジェクトで実行
nx affected:build
nx affected:test --base=main
# 依存関係を可視化
nx graph
# 並行実行
nx run-many --target=build --all --parallel=3
共有設定
TypeScript 設定
// packages/tsconfig/base.json
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true,
"declaration": true
},
"exclude": ["node_modules"]
}
// packages/tsconfig/react.json
{
"extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["ES2022", "DOM", "DOM.Iterable"]
}
}
// apps/web/tsconfig.json
{
"extends": "@repo/tsconfig/react.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
ESLint 設定
// packages/config/eslint-preset.js
module.exports = {
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"prettier",
],
plugins: ["@typescript-eslint", "react", "react-hooks"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2022,
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
settings: {
react: {
version: "detect",
},
},
rules: {
"@typescript-eslint/no-unused-vars": "error",
"react/react-in-jsx-scope": "off",
},
};
// apps/web/.eslintrc.js
module.exports = {
extends: ["@repo/config/eslint-preset"],
rules: {
// アプリ固有のルール
},
};
コード共有パターン
パターン 1: 共有 UI コンポーネント
// packages/ui/src/button.tsx
import * as React from 'react';
export interface ButtonProps {
variant?: 'primary' | 'secondary';
children: React.ReactNode;
onClick?: () => void;
}
export function Button({ variant = 'primary', children, onClick }: ButtonProps) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{children}
</button>
);
}
// packages/ui/src/index.ts
export { Button, type ButtonProps } from './button';
export { Input, type InputProps } from './input';
// apps/web/src/app.tsx
import { Button } from '@repo/ui';
export function App() {
return <Button variant="primary">Click me</Button>;
}
パターン 2: 共有ユーティリティ
// packages/utils/src/string.ts
export function capitalize(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1);
}
export function truncate(str: string, length: number): string {
return str.length > length ? str.slice(0, length) + "..." : str;
}
// packages/utils/src/index.ts
export * from "./string";
export * from "./array";
export * from "./date";
// アプリでの使用
import { capitalize, truncate } from "@repo/utils";
パターン 3: 共有型
// packages/types/src/user.ts
export interface User {
id: string;
email: string;
name: string;
role: "admin" | "user";
}
export interface CreateUserInput {
email: string;
name: string;
password: string;
}
// フロントエンドとバックエンドの両方で使用
import type { User, CreateUserInput } from "@repo/types";
ビルド最適化
Turborepo キャッシング
// turbo.json
{
"pipeline": {
"build": {
// ビルドは依存関係が最初にビルドされることに依存
"dependsOn": ["^build"],
// これらの出力をキャッシュ
"outputs": ["dist/**", ".next/**"],
// これらの入力に基づいてキャッシュ (デフォルト: すべてのファイル)
"inputs": ["src/**/*.tsx", "src/**/*.ts", "package.json"]
},
"test": {
// テストを並行実行、ビルドに依存しない
"cache": true,
"outputs": ["coverage/**"]
}
}
}
リモートキャッシング
# Turborepo リモートキャッシュ (Vercel)
npx turbo login
npx turbo link
# カスタムリモートキャッシュ
# turbo.json
{
"remoteCache": {
"signature": true,
"enabled": true
}
}
モノレポの CI/CD
GitHub Actions
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Nx affected コマンド用
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm turbo run build
- name: Test
run: pnpm turbo run test
- name: Lint
run: pnpm turbo run lint
- name: Type check
run: pnpm turbo run type-check
影響を受けたものだけをデプロイ
# 変更されたアプリのみをデプロイ
- name: Deploy affected apps
run: |
if pnpm nx affected:apps --base=origin/main --head=HEAD | grep -q "web"; then
echo "Deploying web app"
pnpm --filter web deploy
fi
ベストプラクティス
- 一貫したバージョニング: ワークスペース全体で依存関係バージョンをロック
- 共有設定: ESLint、TypeScript、Prettier 設定を集約化
- 依存関係グラフ: 循環依存を避け、非循環を保つ
- 効果的なキャッシング: 入力/出力を正しく設定
- 型安全性: フロントエンド/バックエンド間で型を共有
- テスト戦略: パッケージでユニットテスト、アプリで E2E テスト
- ドキュメンテーション: 各パッケージに README を配置
- リリース戦略: バージョニングに Changesets を使用
よくある落とし穴
- 循環依存: A が B に依存、B が A に依存
- ファントム依存: package.json に記載されていない依存を使用
- 不正なキャッシュ入力: Turborepo 入力に必要なファイルが含まれていない
- 過度な共有: 分離すべきコードを共有
- 不足した共有: パッケージ全体でコードを重複
- 大規模モノレポ: 適切なツールなしではビルドが遅くなる
パッケージの公開
# Changesets を使用
pnpm add -Dw @changesets/cli
pnpm changeset init
# Changeset を作成
pnpm changeset
# パッケージをバージョニング
pnpm changeset version
# 公開
pnpm changeset publish
# .github/workflows/release.yml
- name: Create Release Pull Request or Publish
uses: changesets/action@v1
with:
publish: pnpm release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- wshobson
- リポジトリ
- wshobson/agents
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/wshobson/agents / ライセンス: MIT
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。