Chrome扩展消息发送失败:无法建立连接,接收端不存在
解决Chrome扩展深色模式切换的连接错误问题
针对你遇到的「Error sending message: Could not establish connection. Receiving end does not exist」错误,结合你的代码和配置,以下是具体排查和修复方案:
1. 移除冗余的背景页注入逻辑
你的Background.ts中通过chrome.action.onClicked注入内容脚本的代码完全多余——因为manifest.json已经配置了content_scripts自动注入,且当扩展有default_popup时,点击图标只会打开弹窗,不会触发action.onClicked事件。直接删除这段代码即可,避免逻辑混淆。
2. 修正内容脚本的路径配置
当前manifest.json中content_scripts的js路径是["src/content/content.js"],但Vite + crx插件打包后,实际输出的内容脚本路径并非这个相对路径。需要调整为打包后的正确路径:
{ "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"] } ] }
同时修改vite.config.ts,确保内容脚本打包后输出到扩展根目录:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { crx } from "@crxjs/vite-plugin"; import manifest from "./src/manifest.json"; import path from 'path' export default defineConfig({ plugins: [react(), crx({manifest})], build: { rollupOptions: { input: { background: "src/background/background.ts", content: "src/content/content.ts", }, output: { entryFileNames: "[name].js", // 确保输出文件名为content.js、background.js chunkFileNames: "[name].js", assetFileNames: "[name].[ext]" } }, }, resolve: { alias: { '@': path.resolve(__dirname, './src') }, }, })
3. 确保内容脚本正确加载的验证步骤
- 打开目标网站的开发者工具(F12),切换到Console标签,搜索
✅ Content script loaded:- 如果未找到该日志,说明脚本未注入,检查扩展的「站点访问权限」是否设置为「在所有网站上」;同时确认目标页面不是
chrome://、about://等特殊页面(这类页面无法注入内容脚本)。 - 如果日志存在,说明脚本已加载,问题出在消息发送逻辑。
- 如果未找到该日志,说明脚本未注入,检查扩展的「站点访问权限」是否设置为「在所有网站上」;同时确认目标页面不是
4. 优化弹窗的消息发送逻辑
在弹窗发送消息前,先处理内容脚本未注入的情况,添加失败时的自动注入逻辑:
import { useEffect, useState } from "react"; const Popup = () => { const [isDarkMode, setIsDarkMode] = useState(false); useEffect(() => { chrome.storage.sync.get("darkMode", (data) => { setIsDarkMode(data.darkMode ?? false); }); }, []); const toggleDarkMode = () => { chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { const activeTab = tabs[0]; if (!activeTab?.id) { console.error("❌ No active tab found."); alert("Error: No active tab found."); return; } try { // 先尝试发送消息 const response = await chrome.tabs.sendMessage(activeTab.id, { action: "toggle-dark-mode" }); console.log("✅ Response from content script:", response); setIsDarkMode(response.darkMode); chrome.storage.sync.set({ darkMode: response.darkMode }); } catch (error) { // 发送失败,说明脚本未注入,手动注入后重试 console.log("🔄 Injecting content script..."); await chrome.scripting.executeScript({ target: { tabId: activeTab.id }, files: ["content.js"] }); // 注入后再次发送消息 const response = await chrome.tabs.sendMessage(activeTab.id, { action: "toggle-dark-mode" }); console.log("✅ Response after injection:", response); setIsDarkMode(response.darkMode); chrome.storage.sync.set({ darkMode: response.darkMode }); } }); }; return ( <div className="w-48 p-4 flex flex-col items-center bg-white shadow-lg rounded-lg"> <h2 className="text-lg font-semibold mb-2">Dark Mode</h2> <button className={`px-4 py-2 rounded-md text-white ${ isDarkMode ? "bg-gray-800" : "bg-blue-500" }`} onClick={toggleDarkMode} > {isDarkMode ? "Disable Dark Mode" : "Enable Dark Mode"} </button> </div> ); }; export default Popup;
5. 同步存储状态与页面状态
原代码中弹窗的isDarkMode状态仅从存储读取,但未与页面实际状态同步。上述优化后的代码中,在收到内容脚本的响应后,会更新弹窗状态并同步到存储,确保状态一致。
内容的提问来源于stack exchange,提问作者Akhil kumar srivastava
相关产品推荐
相关产品推荐

