/angular-best-practices
Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and rendering efficiency.
$ npx -y skills add sickn33/antigravity-awesome-skills --skill angular-best-practices --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/angular-best-practices
Context preview
The summary Claude sees to decide when to auto-load this skill.
Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and rendering efficiency.
SKILL.md
angular-best-practices.SKILL.mdname: angular-best-practices
description: "Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and rendering efficiency."
risk: safe
source: self
date_added: "2026-02-27"
Angular Best Practices
Comprehensive performance optimization guide for Angular applications. Contains prioritized rules for eliminating performance bottlenecks, optimizing bundles, and improving rendering.
When to Use
Reference these guidelines when:
- Writing new Angular components or pages
- Implementing data fetching patterns
- Reviewing code for performance issues
- Refactoring existing Angular code
- Optimizing bundle size or load times
- Configuring SSR/hydration
---
Rule Categories by Priority
| Priority | Category | Impact | Focus | | -------- | --------------------- | ---------- | ------------------------------- | | 1 | Change Detection | CRITICAL | Signals, OnPush, Zoneless | | 2 | Async Waterfalls | CRITICAL | RxJS patterns, SSR preloading | | 3 | Bundle Optimization | CRITICAL | Lazy loading, tree shaking | | 4 | Rendering Performance | HIGH | @defer, trackBy, virtualization | | 5 | Server-Side Rendering | HIGH | Hydration, prerendering | | 6 | Template Optimization | MEDIUM | Control flow, pipes | | 7 | State Management | MEDIUM | Signal patterns, selectors | | 8 | Memory Management | LOW-MEDIUM | Cleanup, subscriptions |
---
1. Change Detection (CRITICAL)
Use OnPush Change Detection
// CORRECT - OnPush with Signals
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<div>{{ count() }}</div>`,
})
export class CounterComponent {
count = signal(0);
}
// WRONG - Default change detection
@Component({
template: `<div>{{ count }}</div>`, // Checked every cycle
})
export class CounterComponent {
count = 0;
}Prefer Signals Over Mutable Properties
// CORRECT - Signals trigger precise updates
@Component({
template: `
<h1>{{ title() }}</h1>
<p>Count: {{ count() }}</p>
`,
})
export class DashboardComponent {
title = signal("Dashboard");
count = signal(0);
}
// WRONG - Mutable properties require zone.js checks
@Component({
template: `
<h1>{{ title }}</h1>
<p>Count: {{ count }}</p>
`,
})
export class DashboardComponent {
title = "Dashboard";
count = 0;
}Enable Zoneless for New Projects
// main.ts - Zoneless Angular (v20+)
bootstrapApplication(AppComponent, {
providers: [provideZonelessChangeDetection()],
});**Benefits:**
- No zone.js patches on async APIs
- Smaller bundle (~15KB savings)
- Clean stack traces for debugging
- Better micro-frontend compatibility
---
2. Async Operations & Waterfalls (CRITICAL)
Eliminate Sequential Data Fetching
// WRONG - Nested subscriptions create waterfalls
this.route.params.subscribe((params) => {
// 1. Wait for params
this.userService.getUser(params.id).subscribe((user) => {
// 2. Wait for user
this.postsService.getPosts(user.id).subscribe((posts) => {
// 3. Wait for posts
});
});
});
// CORRECT - Parallel execution with forkJoin
forkJoin({
user: this.userService.getUser(id),
posts: this.postsService.getPosts(id),
}).subscribe((data) => {
// Fetched in parallel
});
// CORRECT - Flatten dependent calls with switchMap
this.route.params
.pipe(
map((p) => p.id),
switchMap((id) => this.userService.getUser(id)),
)
.subscribe();Avoid Client-Side Waterfalls in SSR
// CORRECT - Use resolvers or blocking hydration for critical data
export const route: Route = {
path: "profile/:id",
resolve: { data: profileResolver }, // Fetched on server before navigation
component: ProfileComponent,
};
// WRONG - Component fetches data on init
class ProfileComponent implements OnInit {
ngOnInit() {
// Starts ONLY after JS loads and component renders
this.http.get("/api/profile").subscribe();
}
}---
3. Bundle Optimization (CRITICAL)
Lazy Load Routes
// CORRECT - Lazy load feature routes
export const routes: Routes = [
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES),
},
{
path: "dashboard",
loadComponent: () =>
import("./dashboard/dashboard.component").then(
(m) => m.DashboardComponent,
),
},
];
// WRONG - Eager loading everything
import { AdminModule } from "./admin/admin.module";
export const routes: Routes = [
{ path: "admin", component: AdminComponent }, // In main bundle
];Use @defer for Heavy Components
<!-- CORRECT - Heavy component loads on demand -->
@defer (on viewport) {
<app-analytics-chart [data]="data()" />
} @placeholder {
<div class="chart-skeleton"></div>
}
<!-- WRONG - Heavy component in initial bundle -->
<app-analytics-chart [data]="data()" />Avoid Barrel File Re-exports
// WRONG - Imports entire barrel, breaks tree-shaking
import { Button, Modal, Table } from "@shared/components";
// CORRECT - Direct imports
import { Button } from "@shared/components/button/button.component";
import { Modal } from "@shared/components/modal/modal.component";Dynamic Import Third-Party Libraries
// CORRECT - Load heavy library on demand
async loadChart() {
const { Chart } = await import('chart.js');
this.chart = new Chart(this.canvas, config);
}
// WRONG - Bundle Chart.js in main chunk
import { Chart } from 'chart.js';---
4. Rendering Performance (HIGH)
Always Use trackBy with @for
<!-- CORRECT - Efficient DOM updates -->
@for (item of items(); track item.id) {
<app-item-card [item]="item" />
}
<!-- WRONG - EntireRead more
name: angular-best-practices description: "Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and rendering efficiency." risk: safe source: self date_added: "2026-02-27"
Angular Best Practices
Comprehensive performance optimization guide for Angular applications. Contains prioritized rules for eliminating performance bottlenecks, optimizing bundles, and improving rendering.
When to Use
Reference these guidelines when:
- Writing new Angular components or pages
- Implementing data fetching patterns
- Reviewing code for performance issues
- Refactoring existing Angular code
- Optimizing bundle size or load times
- Configuring SSR/hydration
---
Rule Categories by Priority
| Priority | Category | Impact | Focus | | -------- | --------------------- | ---------- | ------------------------------- | | 1 | Change Detection | CRITICAL | Signals, OnPush, Zoneless | | 2 | Async Waterfalls | CRITICAL | RxJS patterns, SSR preloading | | 3 | Bundle Optimization | CRITICAL | Lazy loading, tree shaking | | 4 | Rendering Performance | HIGH | @defer, trackBy, virtualization | | 5 | Server-Side Rendering | HIGH | Hydration, prerendering | | 6 | Template Optimization | MEDIUM | Control flow, pipes | | 7 | State Management | MEDIUM | Signal patterns, selectors | | 8 | Memory Management | LOW-MEDIUM | Cleanup, subscriptions |
---
1. Change Detection (CRITICAL)
Use OnPush Change Detection
// CORRECT - OnPush with Signals
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<div>{{ count() }}</div>`,
})
export class CounterComponent {
count = signal(0);
}
// WRONG - Default change detection
@Component({
template: `<div>{{ count }}</div>`, // Checked every cycle
})
export class CounterComponent {
count = 0;
}Prefer Signals Over Mutable Properties
// CORRECT - Signals trigger precise updates
@Component({
template: `
<h1>{{ title() }}</h1>
<p>Count: {{ count() }}</p>
`,
})
export class DashboardComponent {
title = signal("Dashboard");
count = signal(0);
}
// WRONG - Mutable properties require zone.js checks
@Component({
template: `
<h1>{{ title }}</h1>
<p>Count: {{ count }}</p>
`,
})
export class DashboardComponent {
title = "Dashboard";
count = 0;
}Enable Zoneless for New Projects
// main.ts - Zoneless Angular (v20+)
bootstrapApplication(AppComponent, {
providers: [provideZonelessChangeDetection()],
});**Benefits:**
- No zone.js patches on async APIs
- Smaller bundle (~15KB savings)
- Clean stack traces for debugging
- Better micro-frontend compatibility
---
2. Async Operations & Waterfalls (CRITICAL)
Eliminate Sequential Data Fetching
// WRONG - Nested subscriptions create waterfalls
this.route.params.subscribe((params) => {
// 1. Wait for params
this.userService.getUser(params.id).subscribe((user) => {
// 2. Wait for user
this.postsService.getPosts(user.id).subscribe((posts) => {
// 3. Wait for posts
});
});
});
// CORRECT - Parallel execution with forkJoin
forkJoin({
user: this.userService.getUser(id),
posts: this.postsService.getPosts(id),
}).subscribe((data) => {
// Fetched in parallel
});
// CORRECT - Flatten dependent calls with switchMap
this.route.params
.pipe(
map((p) => p.id),
switchMap((id) => this.userService.getUser(id)),
)
.subscribe();Avoid Client-Side Waterfalls in SSR
// CORRECT - Use resolvers or blocking hydration for critical data
export const route: Route = {
path: "profile/:id",
resolve: { data: profileResolver }, // Fetched on server before navigation
component: ProfileComponent,
};
// WRONG - Component fetches data on init
class ProfileComponent implements OnInit {
ngOnInit() {
// Starts ONLY after JS loads and component renders
this.http.get("/api/profile").subscribe();
}
}---
3. Bundle Optimization (CRITICAL)
Lazy Load Routes
// CORRECT - Lazy load feature routes
export const routes: Routes = [
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES),
},
{
path: "dashboard",
loadComponent: () =>
import("./dashboard/dashboard.component").then(
(m) => m.DashboardComponent,
),
},
];
// WRONG - Eager loading everything
import { AdminModule } from "./admin/admin.module";
export const routes: Routes = [
{ path: "admin", component: AdminComponent }, // In main bundle
];Use @defer for Heavy Components
<!-- CORRECT - Heavy component loads on demand -->
@defer (on viewport) {
<app-analytics-chart [data]="data()" />
} @placeholder {
<div class="chart-skeleton"></div>
}
<!-- WRONG - Heavy component in initial bundle -->
<app-analytics-chart [data]="data()" />Avoid Barrel File Re-exports
// WRONG - Imports entire barrel, breaks tree-shaking
import { Button, Modal, Table } from "@shared/components";
// CORRECT - Direct imports
import { Button } from "@shared/components/button/button.component";
import { Modal } from "@shared/components/modal/modal.component";Dynamic Import Third-Party Libraries
// CORRECT - Load heavy library on demand
async loadChart() {
const { Chart } = await import('chart.js');
this.chart = new Chart(this.canvas, config);
}
// WRONG - Bundle Chart.js in main chunk
import { Chart } from 'chart.js';---
4. Rendering Performance (HIGH)
Always Use trackBy with @for
<!-- CORRECT - Efficient DOM updates -->
@for (item of items(); track item.id) {
<app-item-card [item]="item" />
}
<!-- WRONG - EntireLocal, agent-owned skill stacks for coding agents—from complete catalog access to a reproducible, reviewable plan. Codex or Claude inspects your project and chooses exact skills from the complete local AAS catalog.
Other skills on agentic-awesome-skills.
- /00-andruia-consultant
Arquitecto de Soluciones Principal y Consultor Tecnológico de Andru.ia. Diagnostica y traza la hoja de ruta óptima para proyectos de IA en español.
Open skill - /007
Security audit, hardening, threat modeling (STRIDE/PASTA), Red/Blue Team, OWASP checks, code review, incident response, and infrastructure security for any project.
Open skill - /10-andruia-skill-smith
Ingeniero de Sistemas de Andru.ia. Diseña, redacta y despliega nuevas habilidades (skills) dentro del repositorio siguiendo el Estándar de Diamante.
Open skill - /20-andruia-niche-intelligence
Estratega de Inteligencia de Dominio de Andru.ia. Analiza el nicho específico de un proyecto para inyectar conocimientos, regulaciones y estándares únicos del sector. Actívalo tras definir el nicho.
Open skill - /2slides-ppt-generator
AI-powered presentation generation via the 2slides API — create slides from text, match a reference image style, summarize documents into decks, add AI voice narration, and export pages/audio. Use for any \"make slides\", \"create a deck\", or \"slides from this document\"
Open skill - /3d-web-experience
Expert in building 3D experiences for the web - Three.js, React
Open skill

