Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 102 additions & 28 deletions frontend/angular/advanced-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,37 @@ Always use a unique key in `track`. This allows Angular to move DOM nodes instea
> [!NOTE]
> **Context:** Tree Rendering
### ❌ Bad Practice
Recursive component call without `OnPush` and memoization.
```html
<ng-template #tree let-node>
{{ node.name }}
<ng-container *ngFor="let child of node.children">
<ng-container *ngTemplateOutlet="tree; context: { $implicit: child }"></ng-container>
</ng-container>
</ng-template>
<ng-container *ngTemplateOutlet="tree; context: { $implicit: root }"></ng-container>
```
### ⚠️ Problem
Exponential growth in change detection checks.
Recursive component calls without `OnPush` or memoization cause exponential growth in change detection checks, blocking the main thread during deep tree rendering.
### ✅ Best Practice
Using the `Memoization` pattern or `computed()` to prepare the tree data structure.


```typescript
@Component({
selector: 'app-tree-node',
standalone: true,
imports: [CommonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
{{ node().name }}
@for (child of node().children; track child.id) {
<app-tree-node [node]="child" />
}
`
})
export class TreeNodeComponent {
node = input.required<TreeNode>();
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
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.
## ⚡ 38. Global Styles Leakage
> [!NOTE]
> **Context:** CSS Encapsulation
Expand Down Expand Up @@ -181,54 +203,106 @@ Pay attention to template determinism with SSR.
> [!NOTE]
> **Context:** DI Performance
### ❌ Bad Practice
Calling `inject()` inside a function that loops.
```typescript
processItems(items: Item[]) {
items.forEach(item => {
const logger = inject(LoggerService);
logger.log(item.name);
});
}
```
### ⚠️ Problem
Although `inject` is fast, in hot paths these are unnecessary DI tree lookups.
Although `inject()` is fast, calling it inside hot paths (loops) triggers unnecessary Dependency Injection tree lookups on every iteration, which degrades performance.
### ✅ Best Practice
Inject dependency once at the class/file constant level.

```typescript
export class ItemProcessor {
private logger = inject(LoggerService);

processItems(items: Item[]) {
items.forEach(item => {
this.logger.log(item.name);
});
}
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
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.
## ⚡ 43. Unused Signal Dependencies
> [!NOTE]
> **Context:** Signal Graph
### ❌ Bad Practice
Reading a signal inside `computed` whose value doesn't affect the result (an unexecuted logical branch).
```typescript
effect(() => {
console.log('Value changed:', this.value());
this.analytics.track('Change', this.user()?.id);
});
```
### ⚠️ Problem
Angular dynamically builds the dependency graph. If you accidentally read a signal, it becomes a dependency.
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.
### ✅ Best Practice
Use `untracked()` to read signals whose changes should not trigger a recalculation.


```typescript
effect(() => {
const currentVal = this.value();
untracked(() => {
this.analytics.track('Change', this.user()?.id);
});
console.log('Value changed:', currentVal);
});
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
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.
## ⚡ 44. Excessive Wrappers (`div` soup)
> [!NOTE]
> **Context:** DOM Size
### ❌ Bad Practice
```html
<div><div><div><app-comp></app-comp></div></div></div>
<div *ngIf="isLoggedIn()">
<div class="user-panel">
<app-user-profile></app-user-profile>
</div>
</div>
```
### ⚠️ Problem
Increases DOM tree depth, slowing down Style Recalculation and Layout.
Unnecessary wrapper `<div>` elements deeply nest the DOM tree ("div soup"). This exponentially slows down CSS Style Recalculation, Layout (Reflow), and Paint.
### ✅ Best Practice
Use `<ng-container>` to group elements without creating extra DOM nodes.


```html
@if (isLoggedIn()) {
<ng-container>
<app-user-profile class="user-panel"></app-user-profile>
</ng-container>
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
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.
## ⚡ 45. Neglecting `runOutsideAngular` for Events
> [!NOTE]
> **Context:** High-frequency events
### ❌ Bad Practice
`@HostListener('window:scroll')`
```typescript
@HostListener('window:scroll', ['$event'])
onScroll() {
this.scrollPosition.set(window.scrollY);
}
```
### ⚠️ Problem
Every scroll event triggers Change Detection.
Every scroll, mousemove, or drag event triggers a full Angular Change Detection cycle. High-frequency events will cause immediate UI lag and frame drops.
### ✅ Best Practice
Subscribe manually in `runOutsideAngular` and update the signal only when necessary.

```typescript
export class ScrollTracker {
private zone = inject(NgZone);
scrollPosition = signal(0);

constructor() {
this.zone.runOutsideAngular(() => {
window.addEventListener('scroll', () => {
if (Math.abs(window.scrollY - this.scrollPosition()) > 50) {
this.zone.run(() => this.scrollPosition.set(window.scrollY));
}
});
});
}
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
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.
---
44 changes: 44 additions & 0 deletions frontend/qwik/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
technology: Qwik
domain: frontend
level: Senior/Architect
version: "1.x"
tags: [performance, advanced, qwik, best-practices, clean-code, scalable-code]
ai_role: Senior Qwik Performance Expert
last_updated: 2026-03-22
---

# 🚀 Qwik Advanced Performance Best Practices

[⬆️ Back to Top](#)
# 📖 Context & Scope
- **Primary Goal:** Enforce strict adherence to advanced performance best practices in Qwik.
- **Target Tooling:** Cursor, Windsurf, Antigravity.
- **Tech Stack Version:** Qwik 1.x

## ⚡ II. Advanced Performance

## ⚡ 1. Synchronous Closures
> [!NOTE]
> **Context:** Component Event Handlers
### ❌ Bad Practice
```tsx
const Component = component$(() => {
const handleClick = () => console.log('clicked');
return <button onClick={handleClick}>Click</button>;
});
```
### ⚠️ Problem
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.
### ✅ Best Practice
```tsx
import { component$, $ } from '@builder.io/qwik';

const Component = component$(() => {
const handleClick = $(() => console.log('clicked'));
return <button onClick$={handleClick}>Click</button>;
});
```
### 🚀 Solution
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.
---
7 changes: 7 additions & 0 deletions frontend/qwik/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ const Component = component$(({ onClick$ }: { onClick$: PropFunction<() => void>
```
### 🚀 Solution
Use the `$` suffix (`onClick$`) to mark the prop as a `PropFunction`, allowing Qwik to serialize the closure and load it lazily.

## 📚 Specialized Topics

For further reading, please refer to the following specialized guides:

- [🚀 Advanced Performance](./performance.md)
- [📦 State Management](./state-management.md)
61 changes: 61 additions & 0 deletions frontend/qwik/state-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
technology: Qwik
domain: frontend
level: Senior/Architect
version: "1.x"
tags: [state-management, advanced, qwik, best-practices, clean-code, scalable-code]
ai_role: Senior Qwik State Management Expert
last_updated: 2026-03-22
---

# 🔄 Qwik State Management Best Practices

[⬆️ Back to Top](#)
# 📖 Context & Scope
- **Primary Goal:** Enforce strict adherence to state management best practices in Qwik.
- **Target Tooling:** Cursor, Windsurf, Antigravity.
- **Tech Stack Version:** Qwik 1.x

## ⚡ II. State Management

## ⚡ 1. Storing Unserializable Data
> [!NOTE]
> **Context:** Reactive Stores and State Object
### ❌ Bad Practice
```tsx
import { component$, useStore, useTask$ } from '@builder.io/qwik';

export const MyComponent = component$(() => {
const store = useStore({
ws: null,
});

useTask$(() => {
store.ws = new WebSocket('ws://localhost:8080'); // Throws Serialization Error
});

return <div>Connecting...</div>;
});
```
### ⚠️ Problem
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.
### ✅ Best Practice
```tsx
import { component$, useSignal, useTask$, useVisibleTask$ } from '@builder.io/qwik';

export const MyComponent = component$(() => {
// Use useSignal initialized with undefined on server
const ws = useSignal<WebSocket>();

// Only run in browser (where websocket lives)
useVisibleTask$(() => {
ws.value = new WebSocket('ws://localhost:8080');
return () => ws.value?.close();
});

return <div>Connecting...</div>;
});
```
### 🚀 Solution
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.
---
54 changes: 54 additions & 0 deletions frontend/solidjs/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
technology: SolidJS
domain: frontend
level: Senior/Architect
version: "1.8+"
tags: [performance, advanced, solidjs, best-practices, clean-code, scalable-code]
ai_role: Senior SolidJS Performance Expert
last_updated: 2026-03-22
---

# 🚀 SolidJS Advanced Performance Best Practices

[⬆️ Back to Top](#)
# 📖 Context & Scope
- **Primary Goal:** Enforce strict adherence to advanced performance best practices in SolidJS.
- **Target Tooling:** Cursor, Windsurf, Antigravity.
- **Tech Stack Version:** SolidJS 1.8+

## ⚡ II. Advanced Performance

## ⚡ 1. Suboptimal List Rendering
> [!NOTE]
> **Context:** Rendering large lists in the DOM.
### ❌ Bad Practice
```tsx
function List(props) {
return (
<ul>
{props.items.map(item => (
<li>{item.name}</li>
))}
</ul>
);
}
```
### ⚠️ Problem
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.
### ✅ Best Practice
```tsx
import { For } from 'solid-js';

function List(props) {
return (
<ul>
<For each={props.items}>
{(item) => <li>{item.name}</li>}
</For>
</ul>
);
}
```
### 🚀 Solution
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.
---
7 changes: 7 additions & 0 deletions frontend/solidjs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,10 @@ return <ul><For each={items()}>{item => <li>{item.name}</li>}</For></ul>;
```
### 🚀 Solution
Use the `<For>` component. It caches DOM elements and handles granular updates when the array changes.

## 📚 Specialized Topics

For further reading, please refer to the following specialized guides:

- [🚀 Advanced Performance](./performance.md)
- [📦 State Management](./state-management.md)
Loading
Loading