[ISSUE-0024] 扩展 reload 后 main.html tab 变成 newtab¶
相关源码:
src/entrypoints/background/index.ts(installListener) 配套被动机制:src/utils/ext-context-guard.ts(v0.10.29)
用户感知的现象¶
用户在 chrome://extensions/?id=<myId> 详情页点击右上角"重新加载"按钮(🔄),
本扩展打开的 main.html / popup / settings / results tab 变成 Chrome 默认新标签页。
引用:
"每次点击刷新后,主界面变成浏览器默认页面的,如何确保不出现这个情况?" "原本是正常的,点刷新就变了,id 是没变的"
根因分析¶
已排除(用户明确)¶
- ❌
manifest.key不固定(不是这个原因 — 用户截图 url 显示 id 没变) - ❌ 硬编码
chrome-extension://<id>URL(同上)
真根因¶
| 阶段 | 现象 |
|---|---|
| 1. 用户点 chrome://extensions 的 reload 按钮 | SW 进程被 kill 重启;所有 chrome-extension://*/ 页面 JS context 失效 |
| 2. ext-context-guard.ts 周期检测(5s) | 还没轮到 → 旧 tab 看起来正常但 JS 已死 |
| 3. 用户在空窗期按浏览器刷新 | Chrome 拒绝 fetch 处于 invalidated 状态的资源 → 替换 tab 为 newtab |
4. 或:guard 触发 location.reload() 时 SW 尚未 ready |
同上结果 |
核心缺陷:src/entrypoints/background/index.ts:277 的 installListener 只处理
reason === 'install' 拉欢迎页,对 update / chrome_update(reload 的真实 reason)没有任何动作。
SW 自己已经 ready 却不主动恢复 tab,纯靠页面侧被动 guard,留下空窗期。
修复方案¶
主动恢复(v0.10.34,本 issue)¶
background/index.ts installListener 加 update 分支:
if (reason === 'update' || reason === 'chrome_update') {
restoreExtensionTabs().catch(...);
}
async function restoreExtensionTabs() {
const myId = browser.runtime.id;
const prefix = `chrome-extension://${myId}/`;
const tabs = await browser.tabs.query({});
for (const tab of tabs) {
if (!tab.id || !tab.url?.startsWith(prefix)) continue;
try { await browser.tabs.reload(tab.id); } catch {}
}
}
与 ext-context-guard 双轨保险¶
| 触发源 | 时机 | 角色 |
|---|---|---|
background onInstalled('update') |
SW 自己 ready 那一刻 | 主动(v0.10.34) |
| 页面侧 5s 周期 + window.error | 5 秒内捕获到失效 | 被动(v0.10.29) |
主动机制先到,几乎不留空窗;被动机制兜底(防止 onInstalled 偶发不触发)。
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/entrypoints/background/index.ts |
installListener 加 update 分支 + restoreExtensionTabs() |
package.json |
0.10.33 → 0.10.34 |
验证方式¶
pnpm build→ 加载到 Chrome- 打开 main.html tab,进入任意页面
- 在 chrome://extensions 点 reload 按钮
- 预期:main.html tab 自动刷新(SW 主动 reload),停留在 main.html
- 不应:变成 newtab / 显示空白
如何避免再犯¶
-
onInstalled不要只处理 install ——update/chrome_update也要主动恢复扩展自身 tab - SW 主动 > 页面被动 —— SW 启动那刻知道自己 ready,比页面侧周期检测早
- 不假设 ext-context-guard 万能 —— 它是兜底,主动机制必须先做
相关问题¶
- 0022-extension-context-invalidated —— guard 机制本身(v0.10.29)
- 扩展reload生命周期 —— MV3 reload 全流程沉淀(v0.10.37 后补建)