Skip to content

Commit aef3586

Browse files
Merge pull request #17 from beginwebdev2002/jules-frontend-agent-refactor-9610771775609385211
refactor(frontend): modularize frontend documentation for Vibe Coding optimization
2 parents 9ece392 + 7d4f3de commit aef3586

18 files changed

Lines changed: 2064 additions & 3358 deletions

frontend/JavaScript/readme.md

Lines changed: 0 additions & 801 deletions
This file was deleted.

frontend/TypeScript/readme.md

Lines changed: 0 additions & 785 deletions
This file was deleted.
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
description: Vibe coding guidelines and architectural constraints for Angular Advanced Performance within the frontend domain.
3+
technology: Angular
4+
domain: frontend
5+
level: Senior/Architect
6+
version: "20"
7+
tags: [performance, advanced, angular, best-practices, clean-code, scalable-code]
8+
ai_role: Senior Angular Performance Expert
9+
last_updated: 2026-03-22
10+
---
11+
12+
# 🚀 Angular Advanced Performance Best Practices & Expert Patterns
13+
14+
# 📖 Context & Scope
15+
- **Primary Goal:** Enforce strict adherence to advanced performance best practices.
16+
- **Target Tooling:** Cursor, Windsurf, Antigravity.
17+
- **Tech Stack Version:** Angular 20
18+
19+
## III. Advanced Performance (31-45)
20+
21+
## 31. Eager Loading of Heavy Components
22+
**Context:** Bundle Size
23+
### ❌ Bad Practice
24+
```html
25+
<app-chart [data]="data" />
26+
```
27+
### ⚠️ Problem
28+
A charting library (e.g., ECharts) loads immediately, blocking TTI (Time to Interactive), even if the chart is below the "fold".
29+
### ✅ Best Practice
30+
```html
31+
@defer (on viewport) {
32+
<app-chart [data]="data" />
33+
} @placeholder {
34+
<div>Loading chart...</div>
35+
}
36+
```
37+
### 🚀 Solution
38+
Use `@defer`. This defers component code loading until a trigger occurs (viewport, interaction, timer).
39+
40+
## 32. Heavy Computation in Main Thread
41+
**Context:** Event Loop Blocking
42+
### ❌ Bad Practice
43+
Sorting an array of 100k elements directly in the component.
44+
### ⚠️ Problem
45+
Freezes the UI.
46+
### ✅ Best Practice
47+
Offload computations to a Web Worker.
48+
### 🚀 Solution
49+
Use Angular Web Workers. In v20, this is easily configured via the CLI.
50+
51+
## 33. Memory Leaks in `effect()`
52+
**Context:** Signal Effects
53+
### ❌ Bad Practice
54+
```typescript
55+
effect(() => {
56+
const timer = setInterval(() => ..., 1000);
57+
// No cleanup
58+
});
59+
```
60+
### ⚠️ Problem
61+
Effects restart when dependencies change. If you don't clean up timers/subscriptions inside an effect, they accumulate.
62+
### ✅ Best Practice
63+
```typescript
64+
effect((onCleanup) => {
65+
const timer = setInterval(() => ..., 1000);
66+
onCleanup(() => clearInterval(timer));
67+
});
68+
```
69+
### 🚀 Solution
70+
Always use the `onCleanup` callback to release resources.
71+
72+
## 34. Excessive Change Detection with `NgZone.run()`
73+
**Context:** Zone Integration
74+
### ❌ Bad Practice
75+
Wrapping third-party libraries in `ngZone.run()` unnecessarily.
76+
### ⚠️ Problem
77+
Forces redundant checks of the entire component tree.
78+
### ✅ Best Practice
79+
```typescript
80+
ngZone.runOutsideAngular(() => {
81+
// Heavy chart rendering or canvas animation
82+
});
83+
```
84+
### 🚀 Solution
85+
Run frequent events (scroll, mousemove, animationFrame) *outside* the Angular zone. Update signals only when UI updates are required.
86+
87+
## 35. Signals equality check default
88+
**Context:** Signal Performance
89+
### ❌ Bad Practice
90+
```typescript
91+
data = signal({ id: 1 }, { equal: undefined }); // Default checks reference
92+
```
93+
### ⚠️ Problem
94+
If you create a new object with the same data `{ id: 1 }`, the signal triggers an update, even though the data hasn't fundamentally changed.
95+
### ✅ Best Practice
96+
```typescript
97+
import { isEqual } from 'lodash-es';
98+
data = signal(obj, { equal: isEqual });
99+
```
100+
### 🚀 Solution
101+
Use a custom comparison function for complex objects to avoid redundant re-renders.
102+
103+
## 36. Lacking `trackBy` in iterables
104+
**Context:** Re-rendering Lists
105+
### ❌ Bad Practice
106+
```html
107+
<li *ngFor="let item of items">{{ item }}</li>
108+
```
109+
### ⚠️ Problem
110+
Without tracking, any array change leads to the recreation of all DOM nodes in the list. $O(n)$ DOM operations.
111+
### ✅ Best Practice
112+
```html
113+
@for (item of items; track item.id)
114+
```
115+
### 🚀 Solution
116+
Always use a unique key in `track`. This allows Angular to move DOM nodes instead of recreating them.
117+
118+
## 37. Recursive Template without Caching
119+
**Context:** Tree Rendering
120+
### ❌ Bad Practice
121+
Recursive component call without `OnPush` and memoization.
122+
### ⚠️ Problem
123+
Exponential growth in change detection checks.
124+
### ✅ Best Practice
125+
Using the `Memoization` pattern or `computed()` to prepare the tree data structure.
126+
127+
## 38. Global Styles Leakage
128+
**Context:** CSS Encapsulation
129+
### ❌ Bad Practice
130+
```css
131+
/* global.css */
132+
button { padding: 10px; }
133+
```
134+
### ⚠️ Problem
135+
Global styles unpredictably affect components.
136+
### ✅ Best Practice
137+
Use `ViewEncapsulation.Emulated` (default) and specific selectors.
138+
### 🚀 Solution
139+
Keep styles locally within components.
140+
141+
## 39. Large Component Bundle
142+
**Context:** Split Chunks
143+
### ❌ Bad Practice
144+
A single huge component of 3000 lines.
145+
### ⚠️ Problem
146+
Poor readability, rendering lazy loading of UI parts impossible.
147+
### ✅ Best Practice
148+
Decompose into "dumb" (UI) and "smart" components.
149+
### 🚀 Solution
150+
Break down the UI into small, reusable blocks.
151+
152+
## 40. Image Optimization Ignorance
153+
**Context:** Core Web Vitals (LCP)
154+
### ❌ Bad Practice
155+
```html
156+
<img src="large-hero.jpg" />
157+
```
158+
### ⚠️ Problem
159+
The browser loads the full image, shifting the layout (CLS).
160+
### ✅ Best Practice
161+
```html
162+
<img ngSrc="hero.jpg" width="800" height="600" priority />
163+
```
164+
### 🚀 Solution
165+
Use the `NgOptimizedImage` directive. It automatically handles lazy loading, preconnect, and srcset.
166+
167+
## 41. Hydration Mismatch
168+
**Context:** SSR / SSG
169+
### ❌ Bad Practice
170+
Rendering `Date.now()` or random numbers (`Math.random()`) directly in the template.
171+
### ⚠️ Problem
172+
The server generates one number, the client another. This causes "flickering" and a hydration error; Angular discards the server DOM and renders from scratch.
173+
### ✅ Best Practice
174+
Use stable data or defer random generation until `afterNextRender`.
175+
### 🚀 Solution
176+
Pay attention to template determinism with SSR.
177+
178+
## 42. Synchronous `inject()` inside loops
179+
**Context:** DI Performance
180+
### ❌ Bad Practice
181+
Calling `inject()` inside a function that loops.
182+
### ⚠️ Problem
183+
Although `inject` is fast, in hot paths these are unnecessary DI tree lookups.
184+
### ✅ Best Practice
185+
Inject dependency once at the class/file constant level.
186+
187+
## 43. Unused Signal Dependencies
188+
**Context:** Signal Graph
189+
### ❌ Bad Practice
190+
Reading a signal inside `computed` whose value doesn't affect the result (an unexecuted logical branch).
191+
### ⚠️ Problem
192+
Angular dynamically builds the dependency graph. If you accidentally read a signal, it becomes a dependency.
193+
### ✅ Best Practice
194+
Use `untracked()` to read signals whose changes should not trigger a recalculation.
195+
196+
## 44. Excessive Wrappers (`div` soup)
197+
**Context:** DOM Size
198+
### ❌ Bad Practice
199+
```html
200+
<div><div><div><app-comp></app-comp></div></div></div>
201+
```
202+
### ⚠️ Problem
203+
Increases DOM tree depth, slowing down Style Recalculation and Layout.
204+
### ✅ Best Practice
205+
Use `<ng-container>` to group elements without creating extra DOM nodes.
206+
207+
## 45. Neglecting `runOutsideAngular` for Events
208+
**Context:** High-frequency events
209+
### ❌ Bad Practice
210+
`@HostListener('window:scroll')`
211+
### ⚠️ Problem
212+
Every scroll event triggers Change Detection.
213+
### ✅ Best Practice
214+
Subscribe manually in `runOutsideAngular` and update the signal only when necessary.
215+
216+
---

0 commit comments

Comments
 (0)