Chrome扩展content script注入ES模块后调用内部函数问题求助
Chrome扩展跨ES模块调用及重复注入问题解决方案
1. 解决utils.js重复注入问题
问题原因
你在manifest.json的content_scripts配置项中同时注册了utils.js,导致页面加载时 manifest 自动注入一次,script.js 动态注入时又触发第二次,引发逻辑冲突。
修复步骤
- 打开
manifest.json,在content_scripts字段中仅保留script.js的注册配置,删除utils.js、core.js的相关配置 - 补充
web_accessible_resources配置,允许页面访问扩展内的模块文件(manifest V3 示例):
{ "web_accessible_resources": [ { "resources": ["modules/*.js"], "matches": ["<all_urls>"] } ] }
说明:matches可替换为你实际需要适配的站点规则,缩小权限范围提升安全性
2. 实现script.js调用core.js的start()函数
原理说明
Content Script 和注入到页面上下文的ES模块属于完全隔离的执行环境,无法直接互相调用函数,需要通过window.postMessage实现跨环境通信触发执行。
代码改造步骤
第一步:优化注入函数,支持加载完成回调
修改script.js中的injectScript为Promise形式,确保依赖加载完成后再触发逻辑:
function injectScript(scriptURL) { return new Promise((resolve) => { const script = document.createElement('script'); script.type = 'module'; script.src = chrome.runtime.getURL(scriptURL); // 调用runtime.getURL获取扩展资源的正确路径 script.onload = resolve; const container = document.head || document.documentElement; container.insertBefore(script, container.lastChild); }) }
第二步:修改core.js,监听执行信号
在core.js末尾添加消息监听逻辑,收到合法信号时执行start():
// 仅接收来自本扩展Content Script的消息,避免恶意调用 window.addEventListener('message', (event) => { if (event.source !== window || event.data?.from !== 'my_extension') return; if (event.data.action === 'run_start') { start(); // 执行目标函数 // 若需要返回执行结果,可通过event.source.postMessage回传即可 } })
第三步:修改script.js的校验逻辑,校验通过后触发执行
调整原有的URL校验后逻辑,按依赖顺序注入模块,加载完成后发送执行信号:
chrome.runtime.sendMessage({ command: 'currentTab' }, async (tab) => { // 替换为你自己的URL校验规则 const allowedHosts = ['example.com', 'test.com']; const tabUrl = new URL(tab.url); if (allowedHosts.includes(tabUrl.host)) { // 按依赖顺序注入,先注入utils再注入core await injectScript('/modules/utils.js'); await injectScript('/modules/core.js'); // 发送执行信号 window.postMessage({ from: 'my_extension', action: 'run_start' }, tabUrl.origin) // 严格指定消息接收源,提升安全性 } })
内容的提问来源于stack exchange,提问作者Dexter
相关产品推荐
相关产品推荐

