perf(frontend): fix slow UI rendering after /api/view response#36
Merged
Conversation
- Add ChangeDetectionStrategy.OnPush to AppComponent and TorrentComponent so change detection only runs when @input references change, not on every mouse move or timer tick - Track filteredCount in AppComponent to replace the duplicate torrentSearch pipe call in the footer (was filtering the full array twice per CD cycle) - Fix orderBy pipe mutating the input array in-place via values.sort(); use [...values].sort() to avoid corrupting this.torrents - Switch polling mergeMap to switchMap to cancel in-flight requests when a new poll fires before the previous response returns Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AppComponentandTorrentComponent— Angular now only re-evaluates components when@Inputreferences change ormarkForCheck()is called, instead of on every mouse move, timer tick, and click event across the full component treetorrentSearchpipe call — the footer torrent count was re-running the O(n) filter independently of the main list render; afilteredCountproperty is now computed once in TypeScript whenever torrents update or the search term changesorderBypipe in-place mutation —values.sort()was silently mutatingthis.torrentswhen no search term was active; changed to[...values].sort()mergeMap→switchMapfor polling — cancels in-flight/api/viewrequests when a new poll fires before the previous response returnsRoot cause
The
/api/viewAPI call was fast. The bottleneck was Angular's default change detection: withoutOnPush, the entire component tree (including all N torrent cards and their 7 pipes each) was re-evaluated on every browser event and every 2-second timer tick. The duplicate pipe call compounded this by running the array filter twice per cycle.Test plan
ng serveand open the app with 10+ torrents activemarkForCheck()inrefreshAfter)🤖 Generated with Claude Code