每当我第一次加载扩展程序(我在开发模式下执行)或重新加载扩展程序时,我都会在background.js中得到未定义的响应(检索HTML内容时出错:未定义)。 错误为,未检查的runtime.lastError:无法建立连接。接收端不存在。
我的文件夹结构是
刮刀 距离/ 民众/ 图片/ 索引.html 清单.json 源代码/ 扩展/ 背景.js 内容脚本.js 应用程序.tsx 实用程序/ chrome-api.js
应用程序.tsx
import React, { useEffect } from 'react';
import './App.css';
import { useRecoilState } from 'recoil';
import messagesState from './states/messages';
import { isValidChromeRuntime } from './utils/chrome-api';
function App() {
const [htmlContent, setHtmlContent] = useRecoilState(messagesState);
const scrapeTab = () => {
if (chrome && chrome.runtime) {
chrome.runtime.sendMessage({ action: 'getHTML' }, function (response) {
console.log(response);
if (response) {
setHtmlContent(response);
} else {
console.error('Error retrieving HTML content:', response);
}
});
} else {
console.error(
'Chrome API is not available. Make sure this component is running in a Chrome extension context.',
chrome
);
}
};
useEffect(() => {
if (isValidChromeRuntime()) {
scrapeTab();
} else {
console.log('here');
}
}, []);
return (
<div className="App">
<h1>Slack scraper</h1>
{JSON.stringify(htmlContent)}
</div>
);
}
export default App;
背景.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action === 'getHTML') {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
if (tabs.length) {
chrome.tabs.sendMessage(
tabs[0].id,
{ action: 'getHTML' },
function (response) {
if (response) {
sendResponse(response);
} else {
console.error('Error retrieving HTML content:', response);
}
}
);
}
});
return true;
}
});
contentScript.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action === 'getHTML') {
const messages = scrapeTheDoc();
sendResponse(messages);
}
});
const scrapeTheDoc = () => {
const container = document.querySelector('.p-workspace__primary_view_body');
return container.toString();
};
document.addEventListener('scroll', function () {
chrome.runtime.sendMessage({ action: 'scrollEvent' });
});
manifest.json
{
"manifest_version": 3,
"name": "scraper",
"version": "1.0",
"description": "Scraper",
"host_permissions": ["<all_urls>"],
"icons": {
"16": "images/logo.png",
"32": "images/logo.png",
"180": "images/logo.png",
"192": "images/logo.png",
"512": "images/logo.png"
},
"offline_enabled": true,
"permissions": ["storage", "activeTab", "contextMenus", "tabs"],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"]
}
],
"action": {
"default_popup": "index.html"
}
}
chrome-api.js
export const isValidChromeRuntime = () => {
return chrome.runtime && !!chrome.runtime.getManifest();
};
webpack.config.js
const HTMLPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');
module.exports = {
entry: {
background: './src/extensions/background.js',
contentScript: './src/extensions/contentScript.js',
popup: './src/index.tsx',
},
mode: 'production',
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
plugins: [
new HTMLPlugin({
template: './public/index.html',
chunks: ['popup'],
filename: 'index.html',
}),
new CopyWebpackPlugin({
patterns: [
{
from: './public',
to: '',
globOptions: {
ignore: ['**/index.html'],
},
},
],
}),
],
};
您对问题的分析表明对内容和后台脚本之间的通信流程存在误解。根据提供的代码片段,您似乎正在尝试从活动选项卡中抓取 HTML 内容,然后将其转发到后台脚本以进行进一步处理。
但是,您当前的方法存在一些不一致和低效的地方:
通信流程:您当前的设置涉及内容脚本向后台脚本发送消息以使用
scrapeTheDoc
提取 HTML,但后台脚本中不会进一步利用此 HTML 内容。
消息结构:内容脚本和后台脚本之间交换的消息格式似乎不一致。最初,您使用
{ action: 'getHTML' }
来请求 HTML 内容,但随后您发送的 HTML 内容本身没有清晰的结构。
为了解决这些问题并改进扩展的功能,我建议采用以下方法:
内容脚本修改:抓取文档应该保留在内容脚本中,因为它直接与 DOM 交互。抓取 HTML 后,将其发送到带有适当操作标识符的后台脚本,例如
{ action: "content", data: HTMLScraped }
。
后台脚本处理:修改后台脚本来处理接收到的HTML内容,并根据需要广播到其他选项卡。确保消息结构一致且易于跨脚本解释。
通过细化通信流程和消息结构,您可以提高分机的可靠性和效率。虽然在没有完整项目的情况下很难进行诊断,但充分实施这些建议应该有助于解决您的具体问题。如果您遇到任何进一步的挑战或需要额外的帮助,请提供更多详细信息以获取进一步的指导。