home / skills / gentleman-programming / gentleman-skills / performance
This skill helps optimize Angular performance by leveraging NgOptimizedImage, @defer, lazy loading, and SSR strategies to improve loading and interactivity.
npx playbooks add skill gentleman-programming/gentleman-skills --skill performanceReview the files below or copy the command above to add this skill to your agents.
---
name: angular-performance
description: >
Angular performance: NgOptimizedImage, @defer, lazy loading, SSR.
Trigger: When optimizing Angular app performance, images, or lazy loading.
metadata:
author: gentleman-programming
version: "1.0"
---
## NgOptimizedImage (REQUIRED for images)
```typescript
import { NgOptimizedImage } from '@angular/common';
@Component({
imports: [NgOptimizedImage],
template: `
<!-- LCP image: add priority -->
<img ngSrc="hero.jpg" width="800" height="400" priority>
<!-- Regular: lazy loaded by default -->
<img ngSrc="thumb.jpg" width="200" height="200">
<!-- Fill mode (parent needs position: relative) -->
<img ngSrc="bg.jpg" fill>
<!-- With placeholder -->
<img ngSrc="photo.jpg" width="400" height="300" placeholder>
`
})
```
### Rules
- ALWAYS set `width` and `height` (or `fill`)
- Add `priority` to LCP (Largest Contentful Paint) image
- Use `ngSrc` not `src`
- Parent of `fill` image must have `position: relative/fixed/absolute`
---
## @defer - Lazy Components
```html
@defer (on viewport) {
<heavy-component />
} @placeholder {
<p>Placeholder shown immediately</p>
} @loading (minimum 200ms) {
<spinner />
} @error {
<p>Failed to load</p>
}
```
### Triggers
| Trigger | When to Use |
|---------|-------------|
| `on viewport` | Below the fold content |
| `on interaction` | Load on click/focus/hover |
| `on idle` | Load when browser is idle |
| `on timer(500ms)` | Load after delay |
| `when condition` | Load when expression is true |
```html
<!-- Multiple triggers -->
@defer (on viewport; on interaction) {
<comments />
}
<!-- Conditional -->
@defer (when showComments()) {
<comments />
}
```
---
## Lazy Routes
```typescript
// Single component
{
path: 'admin',
loadComponent: () => import('./features/admin/admin').then(c => c.AdminComponent)
}
// Feature with child routes
{
path: 'users',
loadChildren: () => import('./features/users/routes').then(m => m.USERS_ROUTES)
}
```
---
## SSR & Hydration
```typescript
bootstrapApplication(AppComponent, {
providers: [
provideClientHydration()
]
});
```
| Scenario | Use |
|----------|-----|
| SEO critical (blog, e-commerce) | SSR |
| Dashboard/Admin | CSR |
| Static marketing site | SSG/Prerender |
---
## Slow Computations
| Solution | When |
|----------|------|
| Optimize algorithm | First choice always |
| Pure pipes | Cache single result |
| Memoization | Cache multiple results |
| `computed()` | Derived signal state |
**NEVER** trigger reflows/repaints in lifecycle hooks (`ngOnInit`, `ngAfterViewInit`).
---
## Resources
- https://angular.dev/guide/image-optimization
- https://angular.dev/guide/defer
- https://angular.dev/best-practices/runtime-performance
- https://angular.dev/guide/ssr
This skill helps you optimize Angular app performance focusing on images, lazy loading, SSR/hydration, and defer-based lazy components. It codifies practical rules for NgOptimizedImage, @defer triggers, lazy routes, slow computation strategies, and when to choose SSR/CSR/SSG. Use it when you need measurable LCP, faster time-to-interactive, and lower bundle sizes.
It inspects image usage and recommends NgOptimizedImage with required attributes (ngSrc, width, height or fill) and LCP priority. It analyzes component loading patterns and suggests @defer triggers (viewport, interaction, idle, timer, condition) and lazy route patterns (loadComponent, loadChildren). It also guides SSR/hydration choices and slow-computation fixes like memoization, pure pipes, or computed signals.
Do I always need width and height on images?
Yes. Always set width and height (or use fill) to prevent layout shifts and help NgOptimizedImage pick sizes.
When should I use @defer(on interaction) vs on viewport?
Use on interaction for features triggered by user action (click/hover/focus). Use on viewport for below-the-fold content that should load when scrolled into view.
When is SSR required instead of CSR?
Choose SSR for SEO-critical pages (blogs, product pages). Use CSR for private dashboards. Consider SSG/prerender for static marketing sites.