feat: 重构录制逻辑,添加错误处理,更新消息常量,使用 terser 进行构建压缩
This commit is contained in:
@@ -19,11 +19,15 @@ export default defineBackground(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 注入 content script
|
// 注入 content script
|
||||||
const res = browser.scripting.executeScript({
|
try {
|
||||||
target: { tabId: tab.id },
|
const res = await browser.scripting.executeScript({
|
||||||
files: ['/content-scripts/content.js'],
|
target: { tabId: tab.id },
|
||||||
});
|
files: ['/content-scripts/content.js'],
|
||||||
console.log('Content script injected on installed/updated:', res);
|
});
|
||||||
|
console.log('Content script injected on installed/updated:', res);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to inject content script:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -36,6 +40,7 @@ export default defineBackground(() => {
|
|||||||
sendResponse({ ok: true });
|
sendResponse({ ok: true });
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
console.error('Failed to check status in content script');
|
||||||
sendResponse({ ok: false });
|
sendResponse({ ok: false });
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@@ -49,6 +54,7 @@ export default defineBackground(() => {
|
|||||||
sendResponse({ ok: true });
|
sendResponse({ ok: true });
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
console.error('Failed to start recording in content script');
|
||||||
sendResponse({ ok: false });
|
sendResponse({ ok: false });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -68,6 +74,14 @@ export default defineBackground(() => {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 监听来自 content script 的消息
|
||||||
|
chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
|
||||||
|
if (msg.type === messages.content.from.saveTrackeEvents) {
|
||||||
|
console.log('[bg] saveTrackeEvents received:', msg.payload);
|
||||||
|
sendResponse({ ok: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
async function sendToActiveTab(message: {
|
async function sendToActiveTab(message: {
|
||||||
type: string;
|
type: string;
|
||||||
data?: unknown;
|
data?: unknown;
|
||||||
@@ -80,6 +94,11 @@ export default defineBackground(() => {
|
|||||||
});
|
});
|
||||||
const activeTab = activeTabs[0];
|
const activeTab = activeTabs[0];
|
||||||
const sendTo = message.activeTabId || activeTab.id;
|
const sendTo = message.activeTabId || activeTab.id;
|
||||||
await chrome.tabs.sendMessage(sendTo!, message);
|
try {
|
||||||
|
await chrome.tabs.sendMessage(sendTo!, message);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error sending message to active tab:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import '../.wxt/types/imports.d.ts';
|
import '../.wxt/types/imports.d.ts';
|
||||||
|
import { createRecorder } from '@/utils/useRecorder';
|
||||||
|
|
||||||
export default defineContentScript({
|
export default defineContentScript({
|
||||||
// matches: ['*://*.google.com/*'],
|
// matches: ['*://*.google.com/*'],
|
||||||
matches: ['<all_urls>'],
|
matches: ['<all_urls>'],
|
||||||
runAt: 'document_start',
|
runAt: 'document_start',
|
||||||
main() {
|
main() {
|
||||||
|
const recorder = createRecorder();
|
||||||
|
|
||||||
// 监听来自 background script 的消息
|
// 监听来自 background script 的消息
|
||||||
chrome.runtime.onMessage.addListener((msg: { type: string }, _sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener((msg: { type: string }, _sender, sendResponse) => {
|
||||||
if (msg.type === messages.content.checkStatus) {
|
if (msg.type === messages.content.checkStatus) {
|
||||||
@@ -16,12 +19,14 @@ export default defineContentScript({
|
|||||||
if (msg.type === messages.content.to.startRecording) {
|
if (msg.type === messages.content.to.startRecording) {
|
||||||
// 开始录制的处理逻辑
|
// 开始录制的处理逻辑
|
||||||
console.log('[content] startRecording received');
|
console.log('[content] startRecording received');
|
||||||
|
recorder.startRecord(messages.content.from.saveTrackeEvents);
|
||||||
sendResponse({ ok: true });
|
sendResponse({ ok: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.type === messages.content.to.stopRecording) {
|
if (msg.type === messages.content.to.stopRecording) {
|
||||||
// 停止录制的处理逻辑
|
// 停止录制的处理逻辑
|
||||||
console.log('[content] stopRecording received');
|
console.log('[content] stopRecording received');
|
||||||
|
recorder.stopRecord();
|
||||||
sendResponse({ ok: true });
|
sendResponse({ ok: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
import { useRef, useState, useCallback } from 'react';
|
|
||||||
|
|
||||||
export const useRecorder = () => {
|
|
||||||
// 存储停止录制函数
|
|
||||||
const stopFnRef = useRef<(() => void) | null>(null);
|
|
||||||
const [isRecording, setIsRecording] = useState(false);
|
|
||||||
|
|
||||||
const startRecord = useCallback(async () => {
|
|
||||||
if (isRecording) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// await chrome.runtime.sendMessage({ type: 'CREATE_OFFSCREEN' });
|
|
||||||
setIsRecording(true);
|
|
||||||
|
|
||||||
console.log('[content] rrweb started');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to start recording:', error);
|
|
||||||
setIsRecording(false);
|
|
||||||
}
|
|
||||||
}, [isRecording]);
|
|
||||||
|
|
||||||
const stopRecord = () => {
|
|
||||||
if (!isRecording) return;
|
|
||||||
|
|
||||||
setIsRecording(false);
|
|
||||||
|
|
||||||
// 停止录制
|
|
||||||
if (stopFnRef.current) {
|
|
||||||
chrome.runtime.sendMessage({ type: 'SAVE_EVENTS' });
|
|
||||||
stopFnRef.current?.();
|
|
||||||
|
|
||||||
console.log('[content] rrweb stopped');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
startRecord,
|
|
||||||
stopRecord,
|
|
||||||
isRecording,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Generated
+38
@@ -44,6 +44,7 @@
|
|||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^16.2.7",
|
"lint-staged": "^16.2.7",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
|
"terser": "^5.46.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.54.0",
|
"typescript-eslint": "^8.54.0",
|
||||||
"wxt": "^0.20.6"
|
"wxt": "^0.20.6"
|
||||||
@@ -1254,6 +1255,17 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@jridgewell/source-map": {
|
||||||
|
"version": "0.3.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz",
|
||||||
|
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.25"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.5.5",
|
"version": "1.5.5",
|
||||||
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||||
@@ -9581,6 +9593,32 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/terser": {
|
||||||
|
"version": "5.46.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/terser/-/terser-5.46.0.tgz",
|
||||||
|
"integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
|
"acorn": "^8.15.0",
|
||||||
|
"commander": "^2.20.0",
|
||||||
|
"source-map-support": "~0.5.20"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"terser": "bin/terser"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/terser/node_modules/commander": {
|
||||||
|
"version": "2.20.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
|
||||||
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/thread-stream": {
|
"node_modules/thread-stream": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/thread-stream/-/thread-stream-3.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/thread-stream/-/thread-stream-3.1.0.tgz",
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^16.2.7",
|
"lint-staged": "^16.2.7",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
|
"terser": "^5.46.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.54.0",
|
"typescript-eslint": "^8.54.0",
|
||||||
"wxt": "^0.20.6"
|
"wxt": "^0.20.6"
|
||||||
|
|||||||
+3
-1
@@ -12,7 +12,9 @@ export const messages = {
|
|||||||
ready: 'popup:ready',
|
ready: 'popup:ready',
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
from: {},
|
from: {
|
||||||
|
saveTrackeEvents: 'content:save-tracke-events',
|
||||||
|
},
|
||||||
to: {
|
to: {
|
||||||
startRecording: 'content:start-recording',
|
startRecording: 'content:start-recording',
|
||||||
stopRecording: 'content:stop-recording',
|
stopRecording: 'content:stop-recording',
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import * as rrweb from 'rrweb';
|
||||||
|
import { listenerHandler } from '@rrweb/types';
|
||||||
|
|
||||||
|
export const createRecorder = () => {
|
||||||
|
let stopFn: listenerHandler | null = null;
|
||||||
|
|
||||||
|
const startRecord = async (msg: string) => {
|
||||||
|
try {
|
||||||
|
// const handler = null;
|
||||||
|
const handler = rrweb.record({
|
||||||
|
emit(event) {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
type: msg,
|
||||||
|
payload: event,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
stopFn = handler || null;
|
||||||
|
|
||||||
|
console.log('[content] rrweb started');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to start recording:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopRecord = () => {
|
||||||
|
if (stopFn) {
|
||||||
|
stopFn();
|
||||||
|
stopFn = null;
|
||||||
|
console.log('[content] rrweb stopped');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { startRecord, stopRecord };
|
||||||
|
};
|
||||||
@@ -31,4 +31,18 @@ export default defineConfig({
|
|||||||
128: 'favicon.ico',
|
128: 'favicon.ico',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
vite: () => ({
|
||||||
|
build: {
|
||||||
|
// 1. 切换压缩器为 terser
|
||||||
|
minify: 'terser',
|
||||||
|
|
||||||
|
// 2. 配置 terser 强制转义所有非 ASCII 字符
|
||||||
|
terserOptions: {
|
||||||
|
format: {
|
||||||
|
ascii_only: true,
|
||||||
|
comments: false, // 去掉注释,防止注释里有乱码
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user