angular-best-practices について
angular-best-practices は、Angular 21 アプリを開発する人向けのスキルです。TypeScript、コンポーネント、Signals、テンプレート、ルーティング、スタイル、アクセシビリティの指針をまとめています。
主な機能
- 01厳密な TypeScript とコンポーネントの指針
- 02Signals による状態管理と非同期リソース
- 03ネイティブなテンプレート制御フロー
- 04機能ルートの遅延読み込み
- 05画像、スタイル、アクセシビリティの指針
活用シーン
- 01新しい Angular プロジェクトの規約策定
- 02コンポーネントと状態パターンの確認
- 03非同期データと遅延ルートの実装
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ boise-state-development/ agentcore-public-stack --skill angular-best-practicesインストール後、Claude Code で/angular-best-practicesを入力して読み込まれたか確認します。
同梱ファイルangular-best-practices.skillsignal-patterns.md
詳細
Angular 21 のベストプラクティス
TypeScript
- 厳密な型チェックを使用します
- 型が明らかな場合は型推論を優先します
anyは避け、型が不明な場合はunknownを使用します
コンポーネント
- 常にスタンドアロンコンポーネントを使用します(
standalone: trueは設定しないでください。v20 以降ではデフォルトです) changeDetection: ChangeDetectionStrategy.OnPushを設定します- デコレーターの代わりに
input()とoutput()関数を使用します - 派生状態には
computed()を使用します - コンポーネントは小さく、単一の責務を持たせます
- 小さなコンポーネントにはインラインテンプレートを優先します
- テンプレート駆動フォームよりリアクティブフォームを使用します
ngClassの代わりにclassバインディングを使用しますngStyleの代わりにstyleバインディングを使用します- 外部テンプレート/スタイルには、コンポーネントの TS ファイルからの相対パスを使用します
@HostBinding/@HostListenerは使用せず、代わりにデコレーター内のhostオブジェクトを使用します
Signals による状態管理
- ローカルのコンポーネント状態にはシグナルを使用します
- 派生状態には
computed()を使用します - 状態の変換は純粋で予測可能なものにします
- シグナルに
mutateは使用せず、代わりにupdateまたはsetを使用します
複雑な派生状態のパターンについては、references/signal-patterns.md を参照してください。
リソース(非同期データ)
シグナルを使った非同期データの取得には resource() を使用します:
const userResource = resource({
params: () => ({ id: userId() }),
loader: ({ params, abortSignal }) => fetch(`/api/users/${params.id}`, { signal: abortSignal }),
});
const userName = computed(() => userResource.hasValue() ? userResource.value().name : undefined);
主な resource パターン:
paramsがundefinedを返すとローダーは実行されず、ステータスは'idle'になります- 実行中のリクエストをキャンセルするには
abortSignalを使用します - 読み込み/エラー状態に対応するため、
value()にアクセスする前にhasValue()を確認します - ステータスの値:
'idle'、'loading'、'reloading'、'resolved'、'error'、'local'
テンプレート
- ネイティブの制御フロー(
@if、@for、@switch)を使用します(*ngIf、*ngFor、*ngSwitchは使用しません) - オブザーバブルには非同期パイプを使用します
- テンプレートはシンプルに保ちます。複雑なロジックは記述しません
- テンプレート内でアロー関数を使用しないでください(サポートされていません)
new Date()などのグローバルが利用可能だと想定しないでください
サービス
- サービスごとに責務を 1 つにします
- シングルトンには
providedIn: 'root'を使用します - コンストラクターインジェクションの代わりに
inject()関数を使用します
@Injectable({ providedIn: 'root' })
export class UserService {
private readonly http = inject(HttpClient);
}
ルーティング
- フィーチャールートには遅延読み込みを実装します:
export const routes: Routes = [
{
path: 'admin',
loadComponent: () => import('./admin/admin.page').then(m => m.AdminPage),
},
];
ファイル名
- ルーティング可能なビューコンポーネント:
file-name.page.ts、file-name.page.html、file-name.page.css - 通常のコンポーネント:
file-name.component.ts - サービス:
file-name.service.ts
アイコン(ng-icon)
import { NgIcon, provideIcons } from '@ng-icons/core';
import { heroSparkles, heroTrash } from '@ng-icons/heroicons/outline';
@Component({
selector: 'app-example',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgIcon],
providers: [provideIcons({ heroSparkles, heroTrash })],
template: `<ng-icon name="heroSparkles" />`,
})
export class ExampleComponent {}
画像
- すべての静的画像に
NgOptimizedImageを使用します - インラインの base64 画像では
NgOptimizedImageは動作しません
スタイリング
- CSS には Tailwind 4.1 を使用します(利用可能であれば Tailwind スキルを参照してください)
- 必要に応じて Angular CDK を利用できます
アクセシビリティ
- すべての AXE チェックに合格する必要があります
- WCAG AA の最低要件(フォーカス管理、色のコントラスト、ARIA 属性)を満たす必要があります
コメント
Markdown 対応