

addEventListener、setInterval、Resize/Mutation/IntersectionObserverMap/Set 持久保存对象,缺少淘汰策略;错误使用 WeakMapObjects allocated between A and BPerformance insights 提示的长任务与重排热点// 错误:未清理
window.addEventListener('resize', onResize)
setInterval(tick, 1000)
// 正确:绑定与清理成对
function mount() {
const handler = () => {}
window.addEventListener('resize', handler)
const timer = setInterval(tick, 1000)
return () => { window.removeEventListener('resize', handler); clearInterval(timer) }
}useEffect(() => {
const io = new IntersectionObserver(/*...*/)
io.observe(ref.current!)
const timer = setInterval(doWork, 1000)
return () => { io.disconnect(); clearInterval(timer) }
}, [])
// 取消可中断请求
useEffect(() => {
const ctrl = new AbortController()
fetch('/api', { signal: ctrl.signal })
return () => ctrl.abort()
}, [id])import { onMounted, onUnmounted } from 'vue'
let timer: number | undefined
onMounted(() => { timer = window.setInterval(tick, 1000) })
onUnmounted(() => { clearInterval(timer) })const mo = new MutationObserver(cb)
mo.observe(node, { childList: true })
// 清理
mo.disconnect()// WebSocket
const ws = new WebSocket(url)
ws.onmessage = handle
// 清理:
ws.close()
ws.onmessage = null
// Worker
const w = new Worker('/worker.js')
w.postMessage({ start: true })
// 清理:
w.terminate()Detached HTMLDivElement 或 Detached DOM treesnull),移除监听,避免全局缓存对 DOM 节点的持有// 易漏:永久持有,越用越大
const cache = new Map<string, any>()
// 改进:WeakMap + LRU + 生命周期清理
const weak = new WeakMap<object, Data>()
// 或显式淘汰策略
class LRU<K,V>{ /*...*/ }注意:WeakMap 仅在没有其他强引用时才可回收;不要将 DOM/对象同时放入强缓存与 WeakMap。
canvas.width = canvas.width 可重置import puppeteer from 'puppeteer'
const runs = 3
;(async () => {
const browser = await puppeteer.launch({ headless: 'new' })
const page = await browser.newPage()
let heaps: number[] = []
for (let i=0;i<runs;i++) {
await page.goto('https://example.com')
await page.waitForSelector('#app')
// 执行关键业务操作...
const mem = await page.evaluate(() => performance && (performance as any).memory ? (performance as any).memory.usedJSHeapSize : 0)
heaps.push(mem)
}
console.log('heap used:', heaps)
await browser.close()
})()趋势持续上升即可能泄漏;结合 performance.measureUserAgentSpecificMemory()(新 API)更精确。
setInterval(() => console.log(process.memoryUsage().heapUsed), 5000)观察路由渲染/请求周期后是否回落;未回落需排查缓存与订阅。
OOM、AbortError、TimeoutError 等与内存快照元数据(路由、设备)add/set/observe 必须配对 remove/clear/disconnectuseResource、EffectScope)统一清理fetch 封装,内置 AbortController 与超时策略useEffect 返回函数、Vue onUnmounted,统一约定Detached 节点与未回收对象disconnect 是否调用terminate 状态与消息管道关闭