开发者深夜调试时受挫自建,抓取 stack trace、API 响应、Next.js 版本等完整上下文,避免 AI 给泛泛答案,每年 2am 救场一次。
那是二月,凌晨两点。我正深陷一个 Next.js 客户端项目,页面彻底挂了。DevTools 像圣诞树一样亮成一片: hydration 错误、API 调用失败、一个来自我根本没写过的依赖的未处理 Promise 拒绝,外加一个 CSP 违规来凑数。
我和所有人一样:复制第一个错误,粘贴到 ChatGPT。回复是?"这可能是由多种原因导致的……"然后跟了一个列表,通用到放在烤面包机上都能用。
当然通用了——我只给了一行代码,没有堆栈跟踪、没有响应体、没有上下文。所以我回去继续:堆栈跟踪、Next.js 版本、TypeScript、失败的 API 响应。复制、粘贴、重复。回答稍微好一点了,但还是没命中,因为 ChatGPT 不知道我的 API 返回了什么。
等我从 DevTools 收集完所有相关信息喂给 ChatGPT,八分钟已经过去了。这还只是一个错误。我还有六个。而且最扎心的是:我的浏览器里已经有 ChatGPT 需要的一切信息。为什么我要在这些标签页之间手动复制来复制去?
如果浏览器能一键捕获所有关键信息——堆栈跟踪、请求、响应、上下文——并包装成一个完美的 AI 提示词呢?火花就是从这里来的。第二天一早,我开始写代码。DebugClip 就此诞生。
我是一个独立开发者。没有团队、没有预算,只有我自己。每个技术决策都归结到:它能帮我省时间吗?它能正常工作吗?
我试过用原生 JS 写扩展。只撑了两小时。我想要的 UI——标签页、实时更新、设置——没有组件的话就是噩梦。React 是必然的选择。TypeScript 对 sanity 至关重要:popup、background worker 和 content script 之间复杂的消息传递意味着类型是我的安全网。
Vite?大多数教程说用 webpack,但 Vite 的开发速度简直离谱。热重载对扩展开发来说为我省了好几天时间。有一个插件叫 @crxjs/vite-plugin,它处理了 Chrome 的 Manifest V3 流水线。没什么争议。
Google 废弃了 Manifest V2,所以我必须为 V3 构建。这意味着没有持久的后台脚本、没有远程代码、更严格的 CSP。这些限制迫使我重新思考一切——从状态存储到脚本注入。
Popup 只有 460px 宽。每一像素都弥足珍贵。Tailwind 让我快速迭代,不用在文件之间切换上下文。深色模式也很简单,我花在布局和信息密度上的时间远比花在任何其他部分的时间多得多。
我的后端只需要验证许可证密钥。Cloudflare Workers 即刻启动,以我的规模来说还是免费的。没有服务器、没有 Docker、没有"但它在我机器上明明能跑"。一条命令就能部署。API 费用?还是零。
我想要一个兼顾 SEO 的静态站点。Next.js 15 加静态导出给了我 React 的架构,但从 Vercel 的边缘网络交付纯 HTML 和 CSS。没有运行时、没有服务器,只要 push 到 git 就上线了。
Chrome 扩展在"隔离世界"中运行 content script。它们看不到 console 错误、fetch 失败或未处理的拒绝。所以我需要把代码注入到页面的实际 JS 上下文中。
使用 chrome.scripting.executeScript 并传入 world: "MAIN",我可以 patch console.error、包装 fetch、监听错误。这几乎在所有地方都有效,除了像 Gmail 或银行应用这样有严格 CSP 的网站。
// 概念:在页面的主世界中 patch console.error
const originalError = console.error;
console.error = function(...args) {
// Store the error for the extension to read later
window.__captured_errors.push({
message: args.map(String).join(' '),
timestamp: Date.now(),
stack: new Error().stack
});
// Always call the original so nothing breaks
originalError.apply(console, args);
};
// Wrapping fetch to catch failures
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const start = Date.now();
try {
const response = await originalFetch(...args);
if (response.status >= 400) {
// Store failed request details
captureNetworkFailure(args[0], response, Date.now() - start);
}
return response;
} catch (err) {
captureNetworkFailure(args[0], null, Date.now() - start);
throw err;
}
};
Chrome 的 debugger API 提供了 DevTools 级别的访问,能捕获所有内容,不管 CSP 如何。代价?它会显示"Debugger attached"的横幅,所以我只在用户打开 popup 时才启用它。
两种策略都向同一个错误存储写入,带有去重机制。一种是静默的,一种是用户主动选择的。
Manifest V3 的 service worker 不是 background page。它会在空闲时死亡,连同所有内存状态一起消失。没有持久的 WebSocket、没有可靠的全局变量。
我的解决方案:将临时数据保留在内存中,但立即将重要内容(设置、许可证、历史)持久化到 chrome.storage.local。
最隐晦的 bug:如果你不从异步的 onMessage handler 返回 true,service worker 可能在响应中途死亡。我因为一个 bug 损失了好几天,许可证激活"有时候能用",因为 worker 会在 API 调用期间消失。
"打开 ChatGPT,粘贴提示词。"听起来很简单。实际上不是。
ChatGPT、Claude、Gemini、DeepSeek 和 Copilot 都是 React SPA。打开一个新标签页,输入框还不存在。你必须等待应用渲染、找到正确的元素(它还在不断变化)、然后以一种 React 能真正感知到的方式注入文本。
// The native setter trick for React-controlled inputs
const textarea = document.querySelector('#prompt-textarea');
const nativeSetter = Object.getOwnPropertyDescriptor(
HTMLTextAreaElement.prototype, 'value'
).set;
nativeSetter.call(textarea, promptText);
textarea.dispatchEvent(new Event('input', { bubbles: true }));
ProseMirror 编辑器(如 Claude)需要你先 focus、然后全选、再用 document.execCommand("insertText")。对于 React,仅仅设置 .value 什么都不会发生——你必须用原生 setter 技巧并分发一个合成的 input 事件。加上时序问题,那些常用技巧(MutationObserver、DOMContentLoaded)都不靠谱。
我的方案:在加载后 1.5s、3.5s、6s 和 10s 时尝试注入。一旦注入成功就标记,然后如果已经完成就退出。不优雅,但管用。
DebugClip 在本地运行。我的 API 成本基本为零。按月定价会迫使我为了加功能而加功能。一次性定价意味着用户不会被"我是不是用得够多?"所困扰,我也不用担心流失。
Pro 版本 4 美元,Ultimate 版本 19 美元。终身授权。对于一个能节省真实开发者时间的工具来说,这很实在。
开发者对他们的 AI 技术栈有强烈的偏好。有人喜欢 Groq(免费且快速),有人有 OpenAI 额度,有人通过工作渠道使用 Anthropic,还有人想要本地优先的方案如 DeepSeek。
只支持一个就会疏远其他所有人。所以我在一个函数下统一了所有 API。新增一个提供商?大约 20 行代码就够了。
React hydration 错误需要的上下文与 Node.js fetch 错误不同。模板将原始错误包装在正确的角色和指令集中,让 AI 真正"以你的技术栈来思考"。做了这个之后,回答质量飙升。
如果你已经厌倦了在 DevTools 和 ChatGPT 之间复制粘贴,DebugClip 已经上线了。
如果你是一个正在考虑推出自己工具的独立开发者?做就是了。第一个版本会很粗糙。这没关系。一个真实用户的反馈永远比三周的额外打磨更有价值。
Originally published on Medium