perf(review): incremental loading, virtualization, and query caching#162
Merged
perf(review): incremental loading, virtualization, and query caching#162
Conversation
…tree list, more perf
Contributor
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR implements virtualization and pagination for pull request review interfaces. It replaces REST-based file summaries with GraphQL batch pagination, introduces a virtualized file tree component, refactors viewport tracking to use refs and reducers instead of state, enhances diff block rendering with improved Pierre/Shiki integration, and switches query handling from single-page to infinite pagination with automatic background loading. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Review Page
participant QC as Query Client
participant GraphQL as GraphQL API
participant Cache as Cache Storage
participant Tree as File Tree UI
Client->>QC: Render with fileSummariesQuery
QC->>Cache: Check cache for initial page
Cache-->>QC: Cache miss or exists
QC->>GraphQL: Fetch first 100 files (cursor: null)
GraphQL-->>QC: Return items + nextCursor
QC->>Cache: Store page 1 results
QC-->>Client: Display initial files + loading indicator
Note over Client,Tree: Background auto-pagination
Client->>QC: Effect detects hasNextPage
QC->>GraphQL: Fetch next batch (cursor: page1.nextCursor)
GraphQL-->>QC: Return items + nextCursor
QC->>Cache: Store page 2 results
Client->>Tree: Render flattened + virtualized items
Tree->>Tree: Show only visible rows at ROW_HEIGHT
Note over Tree: IntersectionObserver tracks<br/>near-viewport and active files
loop While hasNextPage
Client->>QC: Continue auto-fetching background pages
QC->>GraphQL: Fetch paginated results
GraphQL-->>QC: Return page results
QC->>Cache: Accumulate pages
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
This was referenced Apr 22, 2026
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
Overhauls the PR review page to stay responsive on very large PRs (1000+ files). All changes are incremental and maintain existing UX.
Scroll & rendering
IntersectionObserverwas tearing itself down on every state update (its own output was in its deps). Observers are now held in refs and elements are observed imperatively asvisibleFilesgrows.@pierre/diffs/reactand the theme registration at module eval so Suspense boundaries don't queue a waterfall of lazy imports.renderAnnotation,FileHeader,estimateDiffHeight, and splitdiffOptionstheme CSS from structural options so theme toggles don't invalidate every block.Data fetching
listFiles(returned full patches, ~50 MB for 3k files, failed KV cache writes) to GraphQLpullRequest.filesrequesting onlypath,changeType,additions,deletions. ~100× smaller payloads, fits in KV cache.getPullFileSummariesnow takes a cursor and returns one batch of ~500 files (5 GraphQL pages bundled server-side). Client usesuseInfiniteQuerywith a background auto-prefetch effect, so a 3k-file PR renders the first files in ~300 ms instead of a 9 s blank wait.getPullFilesso deeper diffs are in cache by the time the user scrolls to them.additions/deletions/changedFilesdirectly off the PR detail (one query) instead of summing streamed summaries. Chip is accurate on first paint.submitPullReviewinvalidateQueriesto only this PR's keys instead ofgithubQueryKeys.all.Virtualization
@tanstack/react-virtual(fixed 30 px rows). A 1200-node tree mounts ~32 DOM nodes instead of 1200; expand state hoisted to a central Set.Caching
matchesTabQueryinquery-client.tsxnow handles"review"and"commit"tab types, so closing+reopening those tabs rehydrates from localStorage instead of reloading.page/fileSummaries/reviewComments/reviewThreads.files(patches) deliberately excluded — too large for localStorage.Shiki grammar fallback
EXTENSION_TO_FILE_FORMATand redirect any extension mapping to a grammar not in our Shiki bundle →text. No more "Languageobjective-cppnot found" errors; self-healing for any future Pierre additions.Misc
split.Test plan
.h/.rb/Makefilediff — renders as plain text, no Shiki errorSummary by CodeRabbit
New Features
Performance