背景与目标浏览器在页面不可见、后台或即将冻结时会进行资源节流;主动配合生命周期事件可进一步降低资源消耗。保持 BFCache 兼容(避免阻断返回前进缓存),改善回到页面时的恢复体验。核心事件与语义`visibilitychange`:页面可见性变化;`document.visibilityState` 为 `hidden/visible`。`pagehide/pageshow`:页面进入/离开会话历史;`pagehide` 的 `event.persisted` 为 `true` 表示进入 BFCache。`freeze/resume`(Chrome):页面进入/恢复冻结态;可做最后状态持久化与轻量恢复。资源治理:统一暂停与恢复let rafId: number | null = null; let ws: WebSocket | null = null; let activeFetches = new Set<AbortController>(); function startLoop() { const loop = () => { rafId = requestAnimationFrame(loop); // 执行动画与轻量计算 }; if (rafId == null) rafId = requestAnimationFrame(loop); } function stopLoop() { if (rafId != null) { cancelAnimationFrame(rafId); rafId = null; } } function openWS() { if (!ws) ws = new WebSocket('wss://example.com'); } function closeWS() { if (ws) { ws.close(); ws = null; } } function fetchWithAbort(input: RequestInfo, init: RequestInit = {}) { const ac = new AbortController(); activeFetches.add(ac); const merged = { ...init, signal: ac.signal }; return fetch(input, merged).finally(() => activeFetches.delete(ac)); } function abortAllFetches() { activeFetches.forEach(ac => ac.abort()); } function saveState() { // 将必要的 UI/数据状态写入 IndexedDB/localStorage } function restoreState() { // 从持久层恢复必要状态,避免闪烁与不一致 } // 可见性变化:隐藏时暂停、可见时恢复 document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'hidden') { stopLoop(); abortAllFetches(); // 视情况关闭WebSocket,或仅限速 closeWS(); } else { startLoop(); openWS(); } }); // 进入BFCache:不要破坏缓存;尽量停止外部副作用 window.addEventListener('pagehide', (e: PageTransitionEvent) => { saveState(); stopLoop(); // BFCache 允许在返回时快速恢复;避免使用 beforeunload 阻断 abortAllFetches(); closeWS(); }); // 从BFCache恢复或重新载入 window.addEventListener('pageshow', (e: PageTransitionEvent) => { restoreState(); startLoop(); openWS(); }); // Chrome 冻结/恢复事件(存在即用) document.addEventListener('freeze', () => { saveState(); stopLoop(); abortAllFetches(); closeWS(); }); document.addEventListener('resume', () => { restoreState(); startLoop(); openWS(); }); 设计要点与陷阱避免 `beforeunload/unload`:这会使 BFCache 失效,导致返回页面变慢。统一状态管理:将暂停/恢复逻辑封装为可复用模块,确保可见性、pagehide/freeze 路径一致。计时器与动画:`requestAnimationFrame`/`setInterval` 在隐藏态常被节流;仍应主动取消,防止后台累积任务。网络与并发:为所有 `fetch` 提供 `AbortController`;必要时关闭 WebSocket 或降低订阅频率。媒体与图形:暂停 `<video>` 播放、WebAudio、WebGL 绘制;恢复时进行快速 rehydrate,避免过度重建。指标与验证(Chrome 128/Edge 130,桌面+Android)后台 CPU 占用(P95):降低 ≥ 45%。电量消耗(1小时模拟):降低 25%–40%。BFCache 命中率:≥ 85%(移除阻断事件后)。恢复耗时(P95):从后台返回到首屏可交互 ≤ 600ms。资源泄露:长时间后台驻留(30min)无持续增长的 timer/内存。测试策略可见性轮转:每 10s 循环隐藏/显示 30 次,观察 CPU/内存与恢复正确性。BFCache 测试:在 A→B→返回 A 的路径上,确保 `pageshow` 触发且状态被正确恢复。网络与并发:大量并发 `fetch` 在隐藏态能被及时取消,避免后台阻塞。媒体与图形:视频/Canvas 在隐藏态停止渲染,返回时无黑屏或花屏。应用场景长列表与动画页面的节能治理;多数据订阅页面的后台网络降载;WebGL/音频应用的后台安全暂停与迅速恢复。

发表评论 取消回复