You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展Manifest V3中background.js与content.js通信失败排查

Manifest V3 Chrome扩展:Background与Content脚本通信失败问题

问题描述

开发Manifest V3版本Chrome扩展时,遇到以下问题:

  • Background Service Worker(background.js)与Content脚本(content.js)无法通信,无任何报错信息
  • Popup脚本与Background之间的通信可正常进行
  • 扩展控制台能正常打印background.js的日志,网页控制台也能显示content.js的初始加载日志,但两者间的消息传递未生效
  • 已尝试添加多种权限、更换API、创建极简测试项目等方法,均未解决问题

相关代码

manifest.json

{
  "manifest_version": 3,
  "name": "Test",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ],
  "background": {
    "service_worker": "background.js"
  },
  "web_accessible_resources": [
    {
      "resources": ["sounds/test.mp3"],
      "matches": ["<all_urls>"]
    }
  ],
  "permissions": [
    "storage",
    "activeTab",
    "scripting",
    "webNavigation",
    "tabs"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/16.png",
      "48": "icons/48.png",
      "128": "icons/128.png"
    }
  }
}

background.js(原代码)

console.log("BACKGROUND: Playing 60 second audio");
// This works and prints the code in extension console

chrome.runtime.sendMessage({ action: 'playAudio', data: "test.mp3"}); 

content.js(原代码)

console.log("Loading content");

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  console.log("Message received in content script:", message);
    if (message.action === 'playAudio') {
      switch(message.data) {
        case "test.mp3":
          const test = new Audio(chrome.runtime.getURL('sounds/test.mp3'));
          console.log("Playing test");
          test.play();
          break;
      }}
});

问题原因与解决方案

核心原因

Manifest V3中,Background Service Worker使用chrome.runtime.sendMessage是全局广播,但Content脚本属于特定Tab的上下文,若发送消息时未指定目标Tab,或Content脚本尚未完成加载,消息会直接丢失,且不会抛出错误。

解决步骤

1. 切换到chrome.tabs.sendMessage指定目标Tab

将Background中的消息发送方式改为针对特定Tab发送,确保消息能投递到对应Tab的Content脚本。

修改后的background.js:

console.log("BACKGROUND: Playing 60 second audio");

// 获取当前活跃Tab并发送消息
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
  if (tabs.length > 0) {
    chrome.tabs.sendMessage(tabs[0].id, { action: 'playAudio', data: "test.mp3" }, (response) => {
      // 捕获发送失败的情况(如Content脚本未加载)
      if (chrome.runtime.lastError) {
        console.log("消息发送失败:", chrome.runtime.lastError.message);
      }
    });
  }
});

2. 确保Content脚本加载完成后再发送消息

如果需要在页面加载时自动触发消息,可结合webNavigation API监听页面加载完成事件,避免在Content脚本未初始化时发送消息:

// 监听所有页面加载完成事件,发送消息
chrome.webNavigation.onCompleted.addListener((details) => {
  chrome.tabs.sendMessage(details.tabId, { action: 'playAudio', data: "test.mp3" }, (response) => {
    if (chrome.runtime.lastError) {
      console.log("消息发送失败:", chrome.runtime.lastError.message);
    }
  });
}, {url: [{urlMatches: "<all_urls>"}]});

3. 优化Content脚本的消息监听

添加错误捕获,确保消息处理过程中的异常能被发现,同时若涉及异步操作(如音频播放),需返回true以保持消息通道开放:

修改后的content.js:

console.log("Loading content");

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  try {
    console.log("Message received in content script:", message);
    if (message.action === 'playAudio') {
      switch(message.data) {
        case "test.mp3":
          const test = new Audio(chrome.runtime.getURL('sounds/test.mp3'));
          console.log("Playing test");
          // 捕获音频播放失败的异常
          test.play().catch(err => console.log("音频播放失败:", err));
          break;
      }
    }
    // 若有异步响应需求,返回true保持通道
    return true;
  } catch (err) {
    console.log("消息处理出错:", err);
  }
});

内容的提问来源于stack exchange,提问作者Nikola Stankovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 22:50:06