ハイブリッドモード、段階的コンポーネント書き換え、依存性注入更新を使用してAngularJSからAngularへ移行します。AngularJSアプリケーションのアップグレード、フレームワーク移行の計画、またはレガシーAngularコードのモダナイゼーション時に使用します。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Turborepo、Nx、pnpmワークスペースを使用したモノレポ管理をマスターし、最適化されたビルドと依存関係管理で効率的でスケーラブルなマルチパッケージリポジトリを構築。モノレポのセットアップ、ビルドの最適化、共有依存関係の管理時に使用。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
English | 日本語
コード共有、一貫したツール、複数のパッケージとアプリケーション間でのアトミックな変更を可能にする、効率的でスケーラブルなモノレポを構築します。
利点:
課題:
パッケージマネージャー:
ビルドシステム:
# 新しいモノレポを作成
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-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モノレポを作成
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
// 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"]
}
// 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: {
// アプリ固有のルール
},
};
// 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">クリック</Button>;
}
// 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';
// 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';
// 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
}
}
# .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: 依存関係をインストール
run: pnpm install --frozen-lockfile
- name: ビルド
run: pnpm turbo run build
- name: テスト
run: pnpm turbo run test
- name: Lint
run: pnpm turbo run lint
- name: 型チェック
run: pnpm turbo run type-check
# 変更されたアプリのみデプロイ
- name: 影響を受けるアプリをデプロイ
run: |
if pnpm nx affected:apps --base=origin/main --head=HEAD | grep -q "web"; then
echo "webアプリをデプロイ中"
pnpm --filter web deploy
fi
# Changesetsを使用
pnpm add -Dw @changesets/cli
pnpm changeset init
# changesetを作成
pnpm changeset
# パッケージをバージョニング
pnpm changeset version
# 公開
pnpm changeset publish
# .github/workflows/release.yml
- name: リリースPRを作成または公開
uses: changesets/action@v1
with:
publish: pnpm release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
ハイブリッドモード、段階的コンポーネント書き換え、依存性注入更新を使用してAngularJSからAngularへ移行します。AngularJSアプリケーションのアップグレード、フレームワーク移行の計画、またはレガシーAngularコードのモダナイゼーション時に使用します。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
開発者を喜ばせる直感的でスケーラブルで保守可能なAPIを構築するために、RESTとGraphQL APIの設計原則をマスターします。新しいAPIの設計、API仕様のレビュー、またはAPI設計標準の確立時に使用してください。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewing API specifications, or establishing API design standards.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
クリーンアーキテクチャ、ヘキサゴナルアーキテクチャ、ドメイン駆動設計を含む実証済みのバックエンドアーキテクチャパターンを実装します。複雑なバックエンドシステムの設計や、保守性向上のための既存アプリケーションのリファクタリング時に使用します。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.