背景与目标浏览器在页面不可见、后台或即将冻结时会进行资源节流;主动配合生命周期事件可进一步降低资源消耗。保持 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/音频应用的后台安全暂停与迅速恢复。

发表评论 取消回复