Skip to content

Improve search and rendering performance on the cheats index page#5

Open
Rion-Kaneshiro wants to merge 1 commit intoTeeKay87:masterfrom
Rion-Kaneshiro:performance-improvements
Open

Improve search and rendering performance on the cheats index page#5
Rion-Kaneshiro wants to merge 1 commit intoTeeKay87:masterfrom
Rion-Kaneshiro:performance-improvements

Conversation

@Rion-Kaneshiro
Copy link
Copy Markdown

Hey, thanks for maintaining this collection. It's been super useful.

I noticed the index page at list/index.html becomes very sluggish during searches (typing a single letter freezes the UI for a noticeable moment), so I dug into app.js and made a few changes to address it. All existing functionality is preserved (favorites, modal, deep-linking via hash, URL params, keyboard shortcuts).

What was slow

With ~2,400 entries in cheatslist.json, every keystroke triggered:

  1. A full re-filter of the dataset (fast, not the issue)
  2. cardsGrid.innerHTML = '' followed by cloning all matching entries as DOM cards
  3. Every card has an <img> requesting cover art at ?w=1024&thumb=false, so a fresh render fires up to 2,400 image requests at 1024px width

No debounce on the input meant this happened on every single character typed.

Changes

  • Debounced search: 150ms after the last keystroke before filtering. Pressing Enter bypasses the debounce.
  • Batched rendering with IntersectionObserver: renders 60 cards initially, then loads more as the user scrolls (sentinel-based, no library needed). Replaces the all-at-once render.
  • Smaller grid thumbnails: ?w=384 for the grid, ?w=1024 is still used for the modal hero image. Roughly 80% less bandwidth and decode time per card.
  • loading="lazy" + decoding="async" on every cover so the browser only fetches/decodes images near the viewport.
  • Favorite toggle no longer re-renders the whole grid: it just flips the class on the affected card. (When the favorites filter is active and a card is unfavorited, it's removed instead.)
  • Removed cache: 'no-store' from the data fetches so the 2.8MB cheatslist.json can actually be cached between page loads.
  • Precomputed idLower / titleLower on each entry during load. These are referenced in filterEntries() and were being computed (or were absent) in the hot path.

Testing

  • Loaded the full collection locally via python3 -m http.server
  • Stress-tested the search with a variety of titles, IDs, and creator names
  • Verified favorites persist, the modal opens/closes correctly, deep links via #PPSA01521-01.000.000 still work, the back button behaves, and URL params (?q=...&view=favorites) round-trip properly

Possible follow-ups (not in this PR)

  • IndexedDB cache for cheatslist.json so the full dataset doesn't re-download when generation hashes match
  • Optional virtual scrolling once the collection grows past ~5k entries

Happy to split this into smaller commits or adjust anything if you'd prefer a different approach. Cheers!

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 7, 2026

@Rion-Kaneshiro is attempting to deploy a commit to the pcgmr87-7705's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant