Skip to main content

angular

Modern Angular (v20+) expert with deep knowledge of Signals, Standalone Components, Zoneless applications, SSR/Hydration, and reactive patterns.

소스 정보

저장소
davila7/claude-code-templates
최근 소스 활동
2026년 10월 24일 02:19
감지된 SKILL.md 언어
영어
스타
33,139
포크
3,871

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
3 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
angular
description
Modern Angular (v20+) expert with deep knowledge of Signals, Standalone Components, Zoneless applications, SSR/Hydration, and reactive patterns.
metadata
{"risk":"safe","source":"self","date_added":"2026-02-27"}
# Angular Expert Master modern Angular development with Signals, Standalone Components, Zoneless applications, SSR/Hydration, and the latest reactive patterns. ## When to Use This Skill - Building new Angular applications (v20+) - Implementing Signals-based reactive patterns - Creating Standalone Components and migrating from NgModules - Configuring Zoneless Angular applications - Implementing SSR, prerendering, and hydration - Optimizing Angular performance - Adopting modern Angular patterns and best practices ## Do Not Use This Skill When - Migrating from AngularJS (1.x) → use `angular-migration` skill - Working with legacy Angular apps that cannot upgrade - General TypeScript issues → use `typescript-expert` skill ## Instructions 1. Assess the Angular version and project structure 2. Apply modern patterns (Signals, Standalone, Zoneless) 3. Implement with proper typing and reactivity 4. Validate with build and tests ## Safety - Always test changes in development before production - Gradual migration for existing apps (don't big-bang refactor) - Keep backward compatibility during transitions --- ## Angular Version Timeline | Version | Release | Key Features | | -------------- | ------- | ------------------------------------------------------ | | **Angular 20** | Q2 2025 | Signals stable, Zoneless stable, Incremental hydration | | **Angular 21** | Q4 2025 | Signals-first default, Enhanced SSR | | **Angular 22** | Q2 2026 | Signal Forms, Selectorless components | --- ## 1. Signals: The New Reactive Primitive Signals are Angular's fine-grained reactivity system, replacing zone.js-based change detection. ### Core Concepts ```typescript import { signal, computed, effect } from "@angular/core"; // Writable signal const count = signal(0); // Read value console.log(count()); // 0 // Update value count.set(5); // Direct set count.update((v) => v + 1); // Functional update // Computed (derived) signal const doubled = computed(() => count() * 2); // Effect (side effects) effect(() => { console.log(`Count changed to: ${count()}`); }); ``` ### Signal-Based Inputs and Outputs ```typescript import { Component, input, output, model } from "@angular/core"; @Component({ selector: "app-user-card", standalone: true, template: ` <div class="card"> <h3>{{ name() }}</h3> <span>{{ role() }}</span> <button (click)="select.emit(id())">Select</button> </div> `, }) export class UserCardComponent { // Signal inputs (read-only) id = input.required<string>(); name = input.required<string>(); role = input<string>("User"); // With default // Output select = output<string>(); // Two-way binding (model) isSelected = model(false); } // Usage: // <app-user-card [id]="'123'" [name]="'John'" [(isSelected)]="selected" /> ``` ### Signal Queries (ViewChild/ContentChild) ```typescript import { Component, viewChild, viewChildren, contentChild, } from "@angular/core"; @Component({ selector: "app-container", standalone: true, template: ` <input #searchInput /> <app-item *ngFor="let item of items()" /> `, }) export class ContainerComponent { // Signal-based queries searchInput = viewChild<ElementRef>("searchInput"); items = viewChildren(ItemComponent); projectedContent = contentChild(HeaderDirective); focusSearch() { this.searchInput()?.nativeElement.focus(); } } ``` ### When to Use Signals vs RxJS | Use Case | Signals | RxJS | | ----------------------- | --------------- | -------------------------------- | | Local component state | ✅ Preferred | Overkill | | Derived/computed values | ✅ `computed()` | `combineLatest` works | | Side effects | ✅ `effect()` | `tap` operator | | HTTP requests | ❌ | ✅ HttpClient returns Observable | | Event streams | ❌ | ✅ `fromEvent`, operators | | Complex async flows | ❌ | ✅ `switchMap`, `mergeMap` | --- ## 2. Standalone Components Standalone components are self-contained and don't require NgModule declarations. ### Creating Standalone Components ```typescript import { Component } from "@angular/core"; import { CommonModule } from "@angular/common"; import { RouterLink } from "@angular/router"; @Component({ selector: "app-header", standalone: true, imports: [CommonModule, RouterLink], // Direct imports template: ` <header> <a routerLink="/">Home</a> <a routerLink="/about">About</a> </header> `, }) export class HeaderComponent {} ``` ### Bootstrapping Without NgModule ```typescript // main.ts import { bootstrapApplication } from "@angular/platform-browser"; import { provideRouter } from "@angular/router"; import { provideHttpClient } from "@angular/common/http"; import { AppComponent } from "./app/app.component"; import { routes } from "./app/app.routes"; bootstrapApplication(AppComponent, { providers: [provideRouter(routes), provideHttpClient()], }); ``` ### Lazy Loading Standalone Components ```typescript // app.routes.ts import { Routes } from "@angular/router"; export const routes: Routes = [ { path: "dashboard", loadComponent: () => import("./dashboard/dashboard.component").then( (m) => m.DashboardComponent, ), }, { path: "admin", loadChildren: () => import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES), }, ]; ``` --- ## 3. Zoneless Angular Zoneless applications don't use zone.js, improving performance and debugging. ### Enabling Zoneless Mode ```typescript // main.ts import { bootstrapApplication } from "@angular/platform-browser"; import { provideZonelessChangeDetection } from "@angular/core"; import { AppComponent } from "./app/app.component"; bootstrapApplication(AppComponent, { providers: [provideZonelessChangeDetection()], }); ``` ### Zoneless Component Patterns ```typescript import { Component, signal, ChangeDetectionStrategy } from "@angular/core"; @Component({ selector: "app-counter", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` <div>Count: {{ count() }}</div> <button (click)="increment()">+</button> `, }) export class CounterComponent { count = signal(0); increment() { this.count.update((v) => v + 1); // No zone.js needed - Signal triggers change detection } } ``` ### Key Zoneless Benefits - **Performance**: No zone.js patches on async APIs - **Debugging**: Clean stack traces without zone wrappers - **Bundle size**: Smaller without zone.js (~15KB savings) - **Interoperability**: Better with Web Components and micro-frontends --- ## 4. Server-Side Rendering & Hydration ### SSR Setup with Angular CLI ```bash ng add @angular/ssr ``` ### Hydration Configuration ```typescript // app.config.ts import { ApplicationConfig } from "@angular/core"; import { provideClientHydration, withEventReplay, } from "@angular/platform-browser"; export const appConfig: ApplicationConfig = { providers: [provideClientHydration(withEventReplay())], }; ``` ### Incremental Hydration (v20+) ```typescript import { Component } from "@angular/core"; @Component({ selector: "app-page", standalone: true, template: ` <app-hero /> @defer (hydrate on viewport) { <app-comments /> } @defer (hydrate on interaction) { <app-chat-widget /> } `, }) export class PageComponent {} ``` ### Hydration Triggers | Trigger | When to Use | | ---------------- | --------------------------------------- | | `on idle` | Low-priority, hydrate when browser idle | | `on viewport` | Hydrate when element enters viewport | | `on interaction` | Hydrate on first user interaction | | `on hover` | Hydrate when user hovers | | `on timer(ms)` | Hydrate after specified delay | --- ## 5. Modern Routing Patterns ### Functional Route Guards ```typescript // auth.guard.ts import { inject } from "@angular/core"; import { Router, CanActivateFn } from "@angular/router"; import { AuthService } from "./auth.service"; export const authGuard: CanActivateFn = (route, state) => { const auth = inject(AuthService); const router = inject(Router); if (auth.isAuthenticated()) { return true; } return router.createUrlTree(["/login"], { queryParams: { returnUrl: state.url }, }); }; // Usage in routes export const routes: Routes = [ { path: "dashboard", loadComponent: () => import("./dashboard.component"), canActivate: [authGuard], }, ]; ``` ### Route-Level Data Resolvers ```typescript import { inject } from '@angular/core'; import { ResolveFn } from '@angular/router'; import { UserService } from './user.service'; import { User } from './user.model'; export const userResolver: ResolveFn<User> = (route) => { const userService = inject(UserService); return userService.getUser(route.paramMap.get('id')!); }; // In routes { path: 'user/:id', loadComponent: () => import('./user.component'), resolve: { user: userResolver } } // In component export class UserComponent { private route = inject(ActivatedRoute); user = toSignal(this.route.data.pipe(map(d => d['user']))); } ``` --- ## 6. Dependency Injection Patterns ### Modern inject() Function ```typescript import { Component, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { UserService } from './user.service'; @Component({...}) export class UserComponent { // Modern inject() - no constructor needed private http = inject(HttpClient); private userService = inject(UserService); // Works in any injection context users = toSignal(this.userService.getUsers()); } ``` ### Injection Tokens for Configuration
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기