Skip to content
Development
Skill

/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.

From plugin
agentic-awesome-skills
45k200 skills5 agents98 commands
Install
$ npx -y skills add sickn33/antigravity-awesome-skills --skill angular-best-practices --agent claude-code

How 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.md
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 - Entire
Read more
Ships withagentic-awesome-skills

Local, 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.

Get the whole plugin