← ClaudeAtlas

memory-leakslisted

Find and fix frontend memory leaks — missing teardown, growing caches, detached DOM, and closures holding trees alive. Load when a component subscribes to anything, and when a long-lived SPA degrades over time.
soumit-kaz/lazysitter · ★ 1 · Code & Development · score 69
Install: claude install-skill soumit-kaz/lazysitter
# Memory leaks A leak in a page that reloads every few minutes is invisible. In a single-page app a user keeps open all day — a dashboard, an editor, an admin console — it degrades until the tab is unusable, and the bug report says "it gets slow after a while", which nobody can reproduce in a five-minute session. ```bash lazysitter fe-index signals --rule LEAK-NO-TEARDOWN ``` ## The five sources ### 1. Missing effect teardown — by far the most common Every one of these needs a cleanup return: ```jsx useEffect(() => { const id = setInterval(tick, 1000); window.addEventListener('resize', onResize); const obs = new ResizeObserver(cb); obs.observe(el); const sub = stream.subscribe(next); return () => { clearInterval(id); window.removeEventListener('resize', onResize); // the SAME reference obs.disconnect(); sub.unsubscribe(); }; }, []); ``` Each accumulates on **every mount**. A route the user visits ten times has ten intervals firing. Two teardown bugs that look correct: - **`removeEventListener` with a different function reference** removes nothing. An inline arrow in both places creates two distinct functions. - **Clearing a stale timer id** — capturing the id in a closure that has been re-created since. ### 2. Caches without bounds A `Map` keyed by id at module scope, memoized results, an in-memory image cache. Every entry is retained forever, and the keys are usually unbounded (an id per row the user has ever viewed). Bound it: an LRU wit