Chrome扩展Manifest V3动态注入Content Script失效,静态注入正常
你的核心问题是动态注册的Content Script未按预期注入,虽然注册状态显示成功,但实际未加载到页面。以下是具体问题点和修复方案:
1. 未正确收集CSS脚本注册的Promise
你的cssScripts数组通过map生成时,没有返回chrome.scripting.registerContentScripts的Promise对象,导致Promise.all无法等待CSS脚本注册完成,可能引发注册时机紊乱。
修复代码:
const cssScripts = all_settings.sites .filter(site => site.css) .map(site => { // 添加return,收集注册Promise return chrome.scripting.registerContentScripts([{ id: site.name.replace(/\s/g, '_').toLowerCase() + '_css', css: site.css, matches: ["<all_urls>"], runAt: "document_start" }]); });
2. 使用Session Storage导致重复注册或注册丢失
chrome.storage.session的存储仅在当前Service Worker生命周期内有效,当Service Worker因闲置被终止后,存储的registered标记会丢失,导致重复注册;重复注册可能覆盖已有配置但不会报错,进而影响脚本注入逻辑。
修复方案:改用Local Storage持久化标记
// 替换session为local if (!(await chrome.storage.local.get('registered')).registered) { await chrome.storage.local.set({ registered: true }); // ... 后续注册逻辑 }
3. WebNavigation事件注册时机过晚
chrome.webNavigation.onBeforeNavigate触发时,页面已经开始导航流程,此时注册的Content Script无法应用到当前正在加载的页面,仅对后续导航生效。
修复方案:移除不必要的导航监听,仅在关键时机注册
动态注册的Content Script默认persistAcrossSessions: true,注册一次会永久生效(除非手动注销),因此只需在扩展安装/更新、浏览器启动时执行注册:
// 保留安装/更新时的注册 chrome.runtime.onInstalled.addListener(() => registerContentScripts()); // 添加浏览器启动时的注册(防止Service Worker重启后丢失标记) chrome.runtime.onStartup.addListener(() => registerContentScripts()); // 移除这行:chrome.webNavigation.onBeforeNavigate.addListener(registerContentScripts);
4. 动态注册脚本需刷新已有标签页
动态注册的Content Script不会自动回溯应用到已打开的标签页,必须刷新已有标签页或重新打开新标签页才能生效。如果你的测试页面是在注册前打开的,刷新后脚本才会注入。
额外验证点
- 检查
dist/content_scripts/remover.js等脚本的路径是否与打包后的实际文件路径一致,确保扩展能正确访问到这些资源; - 确认
all_settings.sites.flatMap(site => site.matches)生成的匹配规则正确,没有语法错误(比如遗漏*或协议前缀); - 可以在注册时显式设置
persistAcrossSessions: true(默认已开启),确保脚本在浏览器重启后仍保留。
经过以上修复后,动态注册的Content Script应该能正常注入到符合匹配规则的页面中。
内容的提问来源于stack exchange,提问作者Yi Chen Chong

