[ISSUE-0022] Extension context invalidated 错误未处理¶
用户感知的现象¶
错误日志面板看到大量
Error: Extension context invalidated.报错 堆栈指向 React internals chunk 主面板 / popup 可能卡死或部分功能失灵
根因分析¶
Chrome MV3 扩展的经典痛点。
触发链路:
1. 用户在 chrome://extensions 点「刷新」(或 dev 模式热重载、扩展自动更新、disable/enable)
2. Service Worker 重启 → 拿到新的 extension context ID
3. 老的 main.html / popup / settings 标签页还开着 —— 它们的 React 代码持有的 chrome.runtime / browser.* 是上一个 context
4. 老页面继续调 browser.runtime.sendMessage / storage.getItem 等 → 全部抛 Extension context invalidated
5. React useRequest / useEffect 异常 → 错误冒泡到 error boundary 或 console
为什么之前没修: - 错误日志面板(content script 注入的)只是显示给用户看,不影响代码运行 - 真正 broken 的是 polling / 监听器(如 sidebar dataCounts 轮询、settings 自动保存) - 用户没主动反馈过,直到 v0.10.27 推 github + 频繁 reload 导致暴露
修复方案¶
写一个全局 ext-context-guard.ts,在所有 entry 启动时安装:
1. 检测函数¶
function isContextValid(): boolean {
try {
// chrome.runtime.id 访问会在 invalidated 时抛错或返回 undefined
return !!chrome?.runtime?.id;
} catch {
return false;
}
}
2. 全局 error listener¶
function installContextGuard() {
const handle = (msg: string) => {
if (!msg.includes('Extension context invalidated')) return;
showOverlay();
setTimeout(() => location.reload(), 1500);
};
window.addEventListener('error', (e) => handle(e.message || ''));
window.addEventListener('unhandledrejection', (e) => handle(String(e.reason?.message || e.reason || '')));
// 周期性检查(5 秒一次),抓住静默失效(如 polling 内部 catch 吞了错)
setInterval(() => {
if (!isContextValid()) {
showOverlay();
setTimeout(() => location.reload(), 1500);
}
}, 5000);
}
3. UI 覆盖层¶
显示「扩展已更新,正在刷新...」让用户知道发生了什么,避免「页面突然 reload」的困惑感。1.5 秒后自动 reload。
4. 在所有 entry 注入¶
main / popup / settings / results 4 个 entry 启动时调 installContextGuard()。
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/utils/ext-context-guard.ts 🆕 |
guard 主逻辑 + overlay UI |
src/entrypoints/main/main.tsx |
启动时 installContextGuard |
src/entrypoints/popup/main.tsx |
同上 |
src/entrypoints/settings/main.tsx |
同上 |
src/entrypoints/results/main.tsx |
同上 |
验证方式¶
- 加载扩展 + 打开主面板
- 在
chrome://extensions点扩展「刷新」按钮 - 老主面板 tab 应:
- 显示「扩展已更新,正在刷新...」覆盖层
- 1.5 秒后自动 reload
- reload 后页面正常(新 context)
- 错误日志不再堆积 Extension context invalidated
如何避免再犯¶
- Chrome MV3 扩展必装 context guard:任何长寿命 tab(main / settings 独立窗口)都暴露在此风险
- 全局 error listener 是兜底:单点 try/catch 太散,不可能每个 sendMessage 都包
- 5 秒 setInterval 是双保险:万一 listener 漏抓(被某层 catch 吞了),周期检查能抓到
相关问题¶
无 — Chrome MV3 通用问题,与项目业务逻辑无关。