Skip to content

Commit 6dcd12c

Browse files
Merge pull request #41 from beginwebdev2002/refactor-frontend-docs-10398265700506613043
refactor(frontend): optimize Angular snippets and initialize structured docs for SolidJS and Qwik
2 parents 63320a3 + 5b23686 commit 6dcd12c

7 files changed

Lines changed: 333 additions & 28 deletions

File tree

β€Žfrontend/angular/advanced-performance.mdβ€Ž

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,37 @@ Always use a unique key in `track`. This allows Angular to move DOM nodes instea
117117
> [!NOTE]
118118
> **Context:** Tree Rendering
119119
### ❌ Bad Practice
120-
Recursive component call without `OnPush` and memoization.
120+
```html
121+
<ng-template #tree let-node>
122+
{{ node.name }}
123+
<ng-container *ngFor="let child of node.children">
124+
<ng-container *ngTemplateOutlet="tree; context: { $implicit: child }"></ng-container>
125+
</ng-container>
126+
</ng-template>
127+
<ng-container *ngTemplateOutlet="tree; context: { $implicit: root }"></ng-container>
128+
```
121129
### ⚠️ Problem
122-
Exponential growth in change detection checks.
130+
Recursive component calls without `OnPush` or memoization cause exponential growth in change detection checks, blocking the main thread during deep tree rendering.
123131
### βœ… Best Practice
124-
Using the `Memoization` pattern or `computed()` to prepare the tree data structure.
125-
126-
132+
```typescript
133+
@Component({
134+
selector: 'app-tree-node',
135+
standalone: true,
136+
imports: [CommonModule],
137+
changeDetection: ChangeDetectionStrategy.OnPush,
138+
template: `
139+
{{ node().name }}
140+
@for (child of node().children; track child.id) {
141+
<app-tree-node [node]="child" />
142+
}
143+
`
144+
})
145+
export class TreeNodeComponent {
146+
node = input.required<TreeNode>();
147+
}
148+
```
127149
### πŸš€ Solution
128-
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
150+
Use standalone components with `ChangeDetectionStrategy.OnPush` and modern `@for` control flow for recursive structures. This ensures change detection only runs when inputs change, drastically improving performance for deeply nested trees.
129151
## ⚑ 38. Global Styles Leakage
130152
> [!NOTE]
131153
> **Context:** CSS Encapsulation
@@ -181,54 +203,106 @@ Pay attention to template determinism with SSR.
181203
> [!NOTE]
182204
> **Context:** DI Performance
183205
### ❌ Bad Practice
184-
Calling `inject()` inside a function that loops.
206+
```typescript
207+
processItems(items: Item[]) {
208+
items.forEach(item => {
209+
const logger = inject(LoggerService);
210+
logger.log(item.name);
211+
});
212+
}
213+
```
185214
### ⚠️ Problem
186-
Although `inject` is fast, in hot paths these are unnecessary DI tree lookups.
215+
Although `inject()` is fast, calling it inside hot paths (loops) triggers unnecessary Dependency Injection tree lookups on every iteration, which degrades performance.
187216
### βœ… Best Practice
188-
Inject dependency once at the class/file constant level.
189-
217+
```typescript
218+
export class ItemProcessor {
219+
private logger = inject(LoggerService);
190220

221+
processItems(items: Item[]) {
222+
items.forEach(item => {
223+
this.logger.log(item.name);
224+
});
225+
}
226+
}
227+
```
191228
### πŸš€ Solution
192-
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
229+
Inject dependencies exactly once at the class or property level. This caches the reference to the service, bypassing redundant DI resolution and keeping hot paths efficient.
193230
## ⚑ 43. Unused Signal Dependencies
194231
> [!NOTE]
195232
> **Context:** Signal Graph
196233
### ❌ Bad Practice
197-
Reading a signal inside `computed` whose value doesn't affect the result (an unexecuted logical branch).
234+
```typescript
235+
effect(() => {
236+
console.log('Value changed:', this.value());
237+
this.analytics.track('Change', this.user()?.id);
238+
});
239+
```
198240
### ⚠️ Problem
199-
Angular dynamically builds the dependency graph. If you accidentally read a signal, it becomes a dependency.
241+
Angular dynamically builds the signal graph. If you read a signal like `this.user()` inside an effect just for analytics, any change to `user()` will unexpectedly re-trigger the effect, leading to redundant executions.
200242
### βœ… Best Practice
201-
Use `untracked()` to read signals whose changes should not trigger a recalculation.
202-
203-
243+
```typescript
244+
effect(() => {
245+
const currentVal = this.value();
246+
untracked(() => {
247+
this.analytics.track('Change', this.user()?.id);
248+
});
249+
console.log('Value changed:', currentVal);
250+
});
251+
```
204252
### πŸš€ Solution
205-
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
253+
Use `untracked()` to read signals that should not register as dependencies. This prevents unintended re-evaluations and ensures effects only run when their primary state changes.
206254
## ⚑ 44. Excessive Wrappers (`div` soup)
207255
> [!NOTE]
208256
> **Context:** DOM Size
209257
### ❌ Bad Practice
210258
```html
211-
<div><div><div><app-comp></app-comp></div></div></div>
259+
<div *ngIf="isLoggedIn()">
260+
<div class="user-panel">
261+
<app-user-profile></app-user-profile>
262+
</div>
263+
</div>
212264
```
213265
### ⚠️ Problem
214-
Increases DOM tree depth, slowing down Style Recalculation and Layout.
266+
Unnecessary wrapper `<div>` elements deeply nest the DOM tree ("div soup"). This exponentially slows down CSS Style Recalculation, Layout (Reflow), and Paint.
215267
### βœ… Best Practice
216-
Use `<ng-container>` to group elements without creating extra DOM nodes.
217-
218-
268+
```html
269+
@if (isLoggedIn()) {
270+
<ng-container>
271+
<app-user-profile class="user-panel"></app-user-profile>
272+
</ng-container>
273+
}
274+
```
219275
### πŸš€ Solution
220-
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
276+
Utilize `<ng-container>` to apply structural logic or apply classes directly to component hosts. `<ng-container>` is rendered as an invisible comment, keeping the DOM tree shallow and performant.
221277
## ⚑ 45. Neglecting `runOutsideAngular` for Events
222278
> [!NOTE]
223279
> **Context:** High-frequency events
224280
### ❌ Bad Practice
225-
`@HostListener('window:scroll')`
281+
```typescript
282+
@HostListener('window:scroll', ['$event'])
283+
onScroll() {
284+
this.scrollPosition.set(window.scrollY);
285+
}
286+
```
226287
### ⚠️ Problem
227-
Every scroll event triggers Change Detection.
288+
Every scroll, mousemove, or drag event triggers a full Angular Change Detection cycle. High-frequency events will cause immediate UI lag and frame drops.
228289
### βœ… Best Practice
229-
Subscribe manually in `runOutsideAngular` and update the signal only when necessary.
230-
290+
```typescript
291+
export class ScrollTracker {
292+
private zone = inject(NgZone);
293+
scrollPosition = signal(0);
231294

295+
constructor() {
296+
this.zone.runOutsideAngular(() => {
297+
window.addEventListener('scroll', () => {
298+
if (Math.abs(window.scrollY - this.scrollPosition()) > 50) {
299+
this.zone.run(() => this.scrollPosition.set(window.scrollY));
300+
}
301+
});
302+
});
303+
}
304+
}
305+
```
232306
### πŸš€ Solution
233-
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
307+
Bind high-frequency events outside the Angular Zone using `NgZone.runOutsideAngular()`. Only re-enter the Angular Zone (`zone.run()`) when a threshold is met and a UI update is strictly required.
234308
---

β€Žfrontend/qwik/performance.mdβ€Ž

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
technology: Qwik
3+
domain: frontend
4+
level: Senior/Architect
5+
version: "1.x"
6+
tags: [performance, advanced, qwik, best-practices, clean-code, scalable-code]
7+
ai_role: Senior Qwik Performance Expert
8+
last_updated: 2026-03-22
9+
---
10+
11+
# πŸš€ Qwik Advanced Performance Best Practices
12+
13+
[⬆️ Back to Top](#)
14+
# πŸ“– Context & Scope
15+
- **Primary Goal:** Enforce strict adherence to advanced performance best practices in Qwik.
16+
- **Target Tooling:** Cursor, Windsurf, Antigravity.
17+
- **Tech Stack Version:** Qwik 1.x
18+
19+
## ⚑ II. Advanced Performance
20+
21+
## ⚑ 1. Synchronous Closures
22+
> [!NOTE]
23+
> **Context:** Component Event Handlers
24+
### ❌ Bad Practice
25+
```tsx
26+
const Component = component$(() => {
27+
const handleClick = () => console.log('clicked');
28+
return <button onClick={handleClick}>Click</button>;
29+
});
30+
```
31+
### ⚠️ Problem
32+
If you define synchronous functions and bind them to events, Qwik must bundle all that javascript code eagerly, undermining resumability and slowing down the initial page load time.
33+
### βœ… Best Practice
34+
```tsx
35+
import { component$, $ } from '@builder.io/qwik';
36+
37+
const Component = component$(() => {
38+
const handleClick = $(() => console.log('clicked'));
39+
return <button onClick$={handleClick}>Click</button>;
40+
});
41+
```
42+
### πŸš€ Solution
43+
Ensure all event handlers use the `$` suffix (like `onClick$`) and their corresponding logic is wrapped in `$()`. This explicit syntax breaks the application into tiny resumable closures that Qwik can fetch only when the user interacts with them.
44+
---

β€Žfrontend/qwik/readme.mdβ€Ž

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,10 @@ const Component = component$(({ onClick$ }: { onClick$: PropFunction<() => void>
4343
```
4444
### πŸš€ Solution
4545
Use the `$` suffix (`onClick$`) to mark the prop as a `PropFunction`, allowing Qwik to serialize the closure and load it lazily.
46+
47+
## πŸ“š Specialized Topics
48+
49+
For further reading, please refer to the following specialized guides:
50+
51+
- [πŸš€ Advanced Performance](./performance.md)
52+
- [πŸ“¦ State Management](./state-management.md)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
technology: Qwik
3+
domain: frontend
4+
level: Senior/Architect
5+
version: "1.x"
6+
tags: [state-management, advanced, qwik, best-practices, clean-code, scalable-code]
7+
ai_role: Senior Qwik State Management Expert
8+
last_updated: 2026-03-22
9+
---
10+
11+
# πŸ”„ Qwik State Management Best Practices
12+
13+
[⬆️ Back to Top](#)
14+
# πŸ“– Context & Scope
15+
- **Primary Goal:** Enforce strict adherence to state management best practices in Qwik.
16+
- **Target Tooling:** Cursor, Windsurf, Antigravity.
17+
- **Tech Stack Version:** Qwik 1.x
18+
19+
## ⚑ II. State Management
20+
21+
## ⚑ 1. Storing Unserializable Data
22+
> [!NOTE]
23+
> **Context:** Reactive Stores and State Object
24+
### ❌ Bad Practice
25+
```tsx
26+
import { component$, useStore, useTask$ } from '@builder.io/qwik';
27+
28+
export const MyComponent = component$(() => {
29+
const store = useStore({
30+
ws: null,
31+
});
32+
33+
useTask$(() => {
34+
store.ws = new WebSocket('ws://localhost:8080'); // Throws Serialization Error
35+
});
36+
37+
return <div>Connecting...</div>;
38+
});
39+
```
40+
### ⚠️ Problem
41+
Objects like WebSockets, DOM elements, Timeouts, or native Maps/Sets cannot be JSON serialized. Putting them into `useStore` breaks Qwik's core serialization engine, causing fatal errors when the server attempts to transmit state to the client for resumability.
42+
### βœ… Best Practice
43+
```tsx
44+
import { component$, useSignal, useTask$, useVisibleTask$ } from '@builder.io/qwik';
45+
46+
export const MyComponent = component$(() => {
47+
// Use useSignal initialized with undefined on server
48+
const ws = useSignal<WebSocket>();
49+
50+
// Only run in browser (where websocket lives)
51+
useVisibleTask$(() => {
52+
ws.value = new WebSocket('ws://localhost:8080');
53+
return () => ws.value?.close();
54+
});
55+
56+
return <div>Connecting...</div>;
57+
});
58+
```
59+
### πŸš€ Solution
60+
Do not put instances like WebSockets or DOM references into `useStore`. Use `useSignal()` when you need isolated references that initialize lazily on the client using `useVisibleTask$()`, or handle them outside the reactive serialization boundaries.
61+
---
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
technology: SolidJS
3+
domain: frontend
4+
level: Senior/Architect
5+
version: "1.8+"
6+
tags: [performance, advanced, solidjs, best-practices, clean-code, scalable-code]
7+
ai_role: Senior SolidJS Performance Expert
8+
last_updated: 2026-03-22
9+
---
10+
11+
# πŸš€ SolidJS Advanced Performance Best Practices
12+
13+
[⬆️ Back to Top](#)
14+
# πŸ“– Context & Scope
15+
- **Primary Goal:** Enforce strict adherence to advanced performance best practices in SolidJS.
16+
- **Target Tooling:** Cursor, Windsurf, Antigravity.
17+
- **Tech Stack Version:** SolidJS 1.8+
18+
19+
## ⚑ II. Advanced Performance
20+
21+
## ⚑ 1. Suboptimal List Rendering
22+
> [!NOTE]
23+
> **Context:** Rendering large lists in the DOM.
24+
### ❌ Bad Practice
25+
```tsx
26+
function List(props) {
27+
return (
28+
<ul>
29+
{props.items.map(item => (
30+
<li>{item.name}</li>
31+
))}
32+
</ul>
33+
);
34+
}
35+
```
36+
### ⚠️ Problem
37+
Using standard `.map()` for array rendering creates new DOM nodes for every element when the array changes, even if only one item is added or modified. This causes high CPU overhead and negates SolidJS's fine-grained reactivity.
38+
### βœ… Best Practice
39+
```tsx
40+
import { For } from 'solid-js';
41+
42+
function List(props) {
43+
return (
44+
<ul>
45+
<For each={props.items}>
46+
{(item) => <li>{item.name}</li>}
47+
</For>
48+
</ul>
49+
);
50+
}
51+
```
52+
### πŸš€ Solution
53+
Always utilize the built-in `<For>` component. It caches DOM elements and handles granular updates when the array changes, reusing nodes instead of discarding and recreating them.
54+
---

β€Žfrontend/solidjs/readme.mdβ€Ž

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,10 @@ return <ul><For each={items()}>{item => <li>{item.name}</li>}</For></ul>;
4141
```
4242
### πŸš€ Solution
4343
Use the `<For>` component. It caches DOM elements and handles granular updates when the array changes.
44+
45+
## πŸ“š Specialized Topics
46+
47+
For further reading, please refer to the following specialized guides:
48+
49+
- [πŸš€ Advanced Performance](./performance.md)
50+
- [πŸ“¦ State Management](./state-management.md)

0 commit comments

Comments
Β (0)