debugjavascriptMajorpending
Debug: JavaScript memory leak in single-page applications
Viewed 0 times
spa memory leakdetached domevent listener leakuseeffect cleanupabort controller
Error Messages
Problem
Single-page application memory usage grows as users navigate between pages, eventually becoming slow or crashing.
Solution
SPA memory leak detection and common sources:
// DETECTION:
// Chrome DevTools -> Memory tab
// 1. Take heap snapshot
// 2. Navigate around the app
// 3. Take another heap snapshot
// 4. Compare: filter by 'Objects allocated between snapshots'
// 5. Look for: Detached DOM trees, growing arrays
// COMMON LEAK SOURCES:
// LEAK 1: Event listeners not cleaned up on route change
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
// LEAK 2: setInterval/setTimeout not cleared
useEffect(() => {
const id = setInterval(pollData, 5000);
return () => clearInterval(id);
}, []);
// LEAK 3: Fetch requests not aborted
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(r => r.json())
.then(setData)
.catch(e => { if (e.name !== 'AbortError') throw e; });
return () => controller.abort();
}, []);
// LEAK 4: Closures holding DOM references
// After route change, old DOM nodes should be GC'd
// But closures in callbacks can retain them
// LEAK 5: Global stores growing without bounds
// Redux/MobX stores that accumulate data across pages
// Fix: Clear page-specific data on route change
// LEAK 6: Third-party libraries not destroyed
useEffect(() => {
const chart = new Chart(canvasRef.current, config);
return () => chart.destroy();
}, []);Why
SPAs don't get a fresh page on navigation, so leaked resources accumulate. Every effect, listener, timer, and subscription needs explicit cleanup on component unmount.
Context
Single-page application performance
Revisions (0)
No revisions yet.