Chrome扩展Manifest V3中chrome.scripting.executeScript失效问题
Chrome扩展Manifest V3中chrome.scripting.executeScript不执行问题修复
问题根源
点击弹窗按钮跳转页面后,Chrome扩展的popup会自动关闭,导致popup内的脚本上下文被销毁。虽然tabs.onUpdated回调里的alert('a')可能因事件队列残留触发,但后续的chrome.scripting.executeScript调用会因为popup已销毁而无法正常注入脚本到目标页面。手动刷新后再次点击按钮时,popup是在目标页面已加载的状态下运行,不会因页面跳转被关闭,所以API能正常工作。
修复方案:迁移逻辑到Service Worker
将页面跳转、脚本注入的核心逻辑移至Service Worker(后台脚本),它不会随popup关闭而终止,能稳定完成后续操作。
1. 更新manifest.json
添加background配置,指定后台脚本文件:
{ "name": "Scraper", "description": "Simple Extension to Scrape Websites, and Push Them to ConnectionSphere for Data Enrichment", "version": "2.0", "permissions": ["storage", "webRequest", "scripting", "declarativeContent", "activeTab", "tabs", "downloads", "*://*/*", "http://connectionsphere.com:80/*", "http://connectionsphere.com/api1.0/emails/verify.json"], "host_permissions": [ "https://www.amazon.com/*", "https://connectionsphere.com/*", "https://github.com/*" ], "manifest_version": 3, "icons": { "48": "/48.png", "128": "/128.png" }, "action": { "default_popup": "popup.html", "default_icon": { "48": "/48.png", "128": "/128.png" } }, "background": { "service_worker": "background.js" } }
2. 创建background.js
编写后台逻辑,接收popup的消息并处理页面跳转与脚本注入:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === 'scrapePage') { const pageUrl = message.url; chrome.tabs.query({active: true, currentWindow: true}, (tabs) => { const tabId = tabs[0].id; chrome.tabs.update(tabId, {url: pageUrl}, () => { // 监听页面加载完成事件 const loadListener = (updatedTabId, changeInfo) => { if (updatedTabId === tabId && changeInfo.status === 'complete') { chrome.tabs.onUpdated.removeListener(loadListener); // 注入脚本到目标页面 chrome.scripting.executeScript({ target: {tabId: tabId, allFrames: true}, func: () => { alert('b'); document.body.innerHTML = 'hola'; return document.title; } }, (injectionResults) => { if (injectionResults?.length) { // 将结果回传给popup chrome.runtime.sendMessage({result: injectionResults[0].result}); } }); } }; chrome.tabs.onUpdated.addListener(loadListener); }); }); return true; // 保持消息通道开放,支持异步响应 } });
3. 修改popup.js
简化popup逻辑,仅负责发送消息到后台并接收结果:
'use strict'; const text = document.getElementById('text'); const startBtn = document.getElementById('start'); startBtn.onclick = function() { const pageUrl = 'https://github.com/'; text.innerHTML = 'Scraping page...'; // 向后台发送任务消息 chrome.runtime.sendMessage({action: 'scrapePage', url: pageUrl}, (response) => { if (response?.result) { text.innerHTML = response.result; } }); };
额外说明
- 原代码中
chrome.tabs.onUpdated的监听时机存在风险:在chrome.tabs.update之后添加监听,可能错过页面更新事件。迁移到后台后,在tabs.update的回调内添加监听,能确保捕获到目标页面的加载完成状态。 - 通过
func参数注入的函数会被序列化后传入目标页面,函数内部不能引用popup或后台的外部变量,需确保逻辑独立。
内容的提问来源于stack exchange,提问作者LeandroS
相关产品推荐
相关产品推荐

