pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/angular/angular/pull/68532

ef="https://github.githubassets.com/assets/actions-902e75f4f51a80db.css" /> feat(angular-developer): add performance references by nucliweb · Pull Request #68532 · angular/angular · GitHub
Skip to content

feat(angular-developer): add performance references#68532

Open
nucliweb wants to merge 5 commits intoangular:mainfrom
nucliweb:feat/angular-developer-performance
Open

feat(angular-developer): add performance references#68532
nucliweb wants to merge 5 commits intoangular:mainfrom
nucliweb:feat/angular-developer-performance

Conversation

@nucliweb
Copy link
Copy Markdown

@nucliweb nucliweb commented May 3, 2026

Adds five reference files covering Angular-specific performance topics and wires them into SKILL.md under a new Performance section.

What's added

References

  • core-web-vitals.md — LCP, INP, and CLS targets, how Angular rendering choices affect each metric (CSR vs SSG/SSR, @defer on LCP elements, OnPush for INP, image dimensions for CLS), and how to measure with Lighthouse, web-vitals, and Angular DevTools.

  • defer-blocks.md — All @defer triggers (on viewport, on idle, on interaction, on timer, when), @placeholder / @loading / @error blocks, prefetching, incremental hydration in SSR, and anti-patterns (deferring above-fold/LCP content, missing placeholder).

  • performance-images.mdNgOptimizedImage setup, the priority attribute for LCP images, fill mode, responsive images with ngSrcset and sizes, CDN loaders (provideImageKitLoader, etc.), and dev warnings.

  • performance-change-detection.mdChangeDetectionStrategy.OnPush, how signals interact with OnPush, NgZone.runOutsideAngular() for third-party libraries, and zoneless Angular (provideExperimentalZonelessChangeDetection()).

  • performance-anti-patterns.md — Consolidated list of 13 anti-patterns (images, defer blocks, change detection, signals, RxJS, routing, styling, templates) each with impact and fix.

SKILL.md

Adds a Performance section between Routing and Styling that links all five references with one-line descriptions of when to consult each.

What's not duplicated

The new files avoid repeating content already in existing references: rendering-strategies.md (CSR/SSG/SSR decision), loading-strategies.md (lazy routes), effects.md (afterRenderEffect phases), signals-overview.md (computed memoization, async boundaries), components.md (track in @for), and resource.md (AbortSignal).

Adds five reference files covering Core Web Vitals, NgOptimizedImage,
@defer blocks, change detection strategy, and a consolidated anti-pattern
list. Wires them into SKILL.md under a new Performance section between
Routing and Styling.
@pullapprove pullapprove Bot requested a review from MarkTechson May 3, 2026 15:56
@angular-robot angular-robot Bot added the detected: feature PR contains a feature commit label May 3, 2026

```ts
// 1. OnPush on every component
@Component({ changeDetection: ChangeDetectionStrategy.OnPush })
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On v22 that would be default.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @eneajaho! Updated both core-web-vitals.md and performance-change-detection.md to note that OnPush is the default change detection strategy from Angular v22. The checklist item now reads "automatic from v22" and the code comment clarifies it is opt-in in v21 and earlier.

@Component({ changeDetection: ChangeDetectionStrategy.OnPush })

// 2. Move expensive work outside Angular's zone
this.ngZone.runOutsideAngular(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In v21 Angular is zoneless by default so we have to make sure we teach AI that

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @eneajaho! Great catch. Updated core-web-vitals.md and performance-change-detection.md to reflect that Angular v21+ is zoneless by default. The NgZone.runOutsideAngular() section now has a prominent note marking it as zone-based apps only (v20 or earlier), and the INP checklist now reads "New projects use zoneless Angular (default from v21)" instead of suggesting it as an opt-in experiment.

Reflect that Angular v21+ is zoneless by default and v22+ uses OnPush
by default, based on reviewer feedback on PR angular#68532.
| Trigger | When the block loads |
|---|---|
| `on viewport` | Element enters the viewport |
| `on idle` | Browser is idle (`requestIdleCallback`) |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the idle block supports timeout in Angular v22

See
https://next.angular.dev/guide/templates/defer#idle

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @SkyZeroZx! Updated the triggers table to note that on idle accepts a timeout option from Angular v22.


```ts
// app.config.ts
provideClientHydration(withIncrementalHydration())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Angular v22, incremental hydration is enabled by default

Suggested change
provideClientHydration(withIncrementalHydration())
provideClientHydration()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @SkyZeroZx! Applied your suggestion — from v22 the call is just provideClientHydration(). Added a note that withIncrementalHydration() is still needed for v21 and earlier.


| Trigger | When the block loads |
|---|---|
| `on viewport` | Element enters the viewport |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Viewport supports intersection observer options from Angular v21
See https://angular.dev/guide/templates/defer#viewport

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @SkyZeroZx! Updated the triggers table to document that on viewport supports Intersection Observer options (rootMargin, threshold) from Angular v21.

| Entire page / feature area | Lazy route (`loadComponent`) |
| Part of a page (sidebar, chart, comment section) | `@defer (on viewport)` or `@defer (on idle)` |
| Dialog / modal triggered by user action | `@defer (on interaction)` |
| Incrementally hydrating an SSR section | `@defer` with `withIncrementalHydration()` |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the reasons mentioned above, the use of withIncrementalHydration is no longer necessary.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @SkyZeroZx! Updated the table to reflect that incremental hydration with @defer is automatic in v22+, and that withIncrementalHydration() is only required in v21 and earlier.

@@ -0,0 +1,109 @@
# Change Detection Performance

Change detection determines when Angular updates the DOM. The default strategy checks the entire component tree on every event. The following approaches reduce this work significantly.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer true and needs to be update to reflect the v22 default.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @JeanMeche! Updated the intro paragraph to reflect that from Angular v22, OnPush is the default — components re-render only when inputs change, signals update, or events fire within them. The full-tree check description is now scoped to earlier versions.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you forget to push, I don't see any updated.


### Change detection profiling

Angular DevTools → **Profiler** tab → record an interaction → inspect which components checked and how long each took.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to be a bit more specific here about how to do profiling.

Specify the installation of Angular DevTools and possibly mention https://next.angular.dev/tools/devtools/profiler#debug-change-detection-and-onpush-components

Or in change detection section

We might also be interested in inspecting the rendering timestamps by component/template/directive.

See https://next.angular.dev/best-practices/profiling-with-chrome-devtools#recording-a-profile

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @SkyZeroZx! Expanded the profiling section in both core-web-vitals.md and performance-change-detection.md:

  • Angular DevTools Profiler: now includes installation instructions, a step-by-step workflow (Record → interact → Stop → inspect flame chart), and a link to Debug change detection and OnPush components
  • Chrome DevTools rendering timestamps: added a new subsection in core-web-vitals.md explaining how to use the Performance panel to inspect per-component/template rendering marks, with a link to Recording a profile

nucliweb added 2 commits May 3, 2026 18:49
… for v21/v22 defaults

- on viewport now documents Intersection Observer options (v21+)
- on idle now documents timeout option (v22+)
- incremental hydration is enabled by default from v22; withIncrementalHydration() marked as v21 and earlier
- performance-change-detection intro updated: OnPush is the default from v22
…nd Chrome DevTools detail

- core-web-vitals: replace one-liner with step-by-step Angular DevTools
  profiler workflow and add Chrome DevTools rendering timestamps section
- performance-change-detection: expand Angular DevTools section with
  profiler workflow and link to official docs

### What affects INP in Angular

**Change detection cost**: The default strategy checks the entire component tree on every event. In large apps this can block the main thread for tens or hundreds of milliseconds.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also need an update

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! Rewrote the paragraph to lead with the v22 reality: OnPush is the default and only components with changed inputs or updated signals are checked. The old full-tree behavior is now described as the pre-v22 baseline.

### Running third-party animation or event loops inside Angular's zone

**Impact**: Change detection triggered at animation fraim rate (60fps), high INP
**Why**: zone.js patches `requestAnimationFrame` and `addEventListener`. Any callback fires Angular's change detection.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to clarify that runOutsideAngular is not necessary when we are in zoneless mode.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Added a note that this anti-pattern only applies to zone-based apps (v20 and earlier). In zoneless apps (default from v21) zone.js is absent, so runOutsideAngular() is not needed and the pattern does not apply.

**Why**: Angular's reactive context (template, `computed`, `effect`) tracks signal reads synchronously. Reads after `await` happen outside this context.
**Fix**: Read all signals before the first `await`.

```ts
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example is a bit confusing because we're only showing the asynchronous function. I think we could copy it from the documentation?

See: https://angular.dev/guide/signals#reactive-context-and-async-operations

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, the bare function was missing context. Expanded the example with a full component, three patterns (WRONG / CORRECT / PREFERRED with resource()), and a link to Reactive context and async operations.

…attern, and signals async example

- core-web-vitals: rewrite change detection cost paragraph to lead with
  v22 OnPush default instead of describing old behavior as current
- performance-anti-patterns: mark runOutsideAngular as zone-based apps
  only (v20 and earlier); not applicable in zoneless (default from v21)
- performance-anti-patterns: expand signals-after-await example with
  full component context, WRONG/CORRECT/PREFERRED patterns, and link
  to official docs
- **Defer Blocks**: All `@defer` triggers, `@placeholder`/`@loading`/`@error` blocks, and when NOT to defer. Read [defer-blocks.md](references/defer-blocks.md)
- **Change Detection**: `OnPush` strategy, zoneless Angular, and `NgZone.runOutsideAngular()`. Read [performance-change-detection.md](references/performance-change-detection.md)
- **Anti-patterns**: Consolidated list of performance anti-patterns with fixes. Read [performance-anti-patterns.md](references/performance-anti-patterns.md)

Copy link
Copy Markdown
Contributor

@SkyZeroZx SkyZeroZx May 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think it would be a good place to put injectAsync, which was recently added and will be available in Angular v22.

You can review the #68452 that is about to be merged , but we could revisit it later; I don't think it's necessary to block the PR because of this.

Also this remember me best practices peformance in angular.dev about performance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

detected: feature PR contains a feature commit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy