如何使用 ChatGPT 构建 Chrome 浏览器扩展:从零到上架全流程

发布时间:2026/10/3 6:18:26
如何使用 ChatGPT 构建 Chrome 浏览器扩展:从零到上架全流程
1. 零基础用 ChatGPT 写 Chrome 扩展到底难在哪很多人第一次听到「用 ChatGPT 构建 Chrome 浏览器扩展」脑子里冒出来的第一个念头是我连 JavaScript 都没系统学过能行吗我实测下来的结论是——能行但前提是你得知道整个流程里哪些环节 AI 能帮你、哪些环节必须你自己动手确认。Chrome 扩展Chrome Extension本质上就是一堆 HTML、CSS、JavaScript 文件加上一个叫 manifest.json 的配置文件打包成一个文件夹浏览器就能加载运行。它不是什么黑魔法也不需要编译打包成 exe你写完直接拖进浏览器就能跑。那为什么很多人卡住我总结下来有三个真实的坑。第一个坑是 manifest 版本混乱。网上大量教程还在讲 Manifest V2但 Chrome 从 2023 年开始主推 Manifest V3V2 的background.scripts写法在 V3 里直接报错你照着老教程抄加载时就会看到「Manifest version 2 is deprecated」这类提示。第二个坑是权限声明和实际调用对不上比如你在 popup.js 里调了chrome.browsingData但 manifest 里没写browsingData权限运行时直接抛 undefined。第三个坑是 AI 生成的代码「看起来对、跑起来错」因为 ChatGPT 不知道你的 Chrome 版本、不知道你文件夹里到底有没有图标文件它给的代码需要你逐行核对。这篇文章要解决的就是这三个坑。我会带你从零做一个真实可用的扩展原型——一个「一键清理浏览器缓存」的小工具完整走一遍需求拆解、manifest 配置、popup 页面、content script、本地加载调试、直到打包上架的流程。同时我会演示怎么用 TaoToken 这个统一 Key 通道来调用模型辅助生成代码这样你就不用在不同 AI 工具之间来回切换、也不用把 Key 散落在各个平台。适合谁看适合完全没写过扩展、但会用电脑、愿意照着步骤敲代码的零基础开发者。你不需要精通 JS但需要能看懂基本的函数和事件绑定。先说清楚一个预期AI 不会一次给你完美代码。你和它沟通的指令越清晰生成的代码 bug 越少。我试过用一句「帮我写个清缓存的扩展」去问得到的代码缺权限、缺图标、popup 路径还写错但当我按「文件结构 每个文件的职责 具体 API 权限清单」这样结构化地提问基本两三轮就能跑通。所以这篇文章的重点不是「复制粘贴」而是教你一套可复用的提问和验证方法。2. TaoToken 统一 Key 通道接入前的准备与配置在正式写代码之前先解决「用哪个模型来辅助生成代码」这件事。你当然可以直接开 ChatGPT 网页版但实际开发中你会发现一个问题写扩展时你需要在编辑器、浏览器、AI 对话之间反复切换而且不同模型的 Key 管理很麻烦。TaoToken 的思路是提供一个统一的 API 通道你用同一个 Key 就能调用多种模型省去到处注册、到处贴 Key 的麻烦。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 。这里要强调一点TaoToken 是合规的模型调用通道不是所谓「中转」的灰色服务你把它理解成一个统一的 API 网关就行。它的价值在于你在写扩展的过程中可以让编辑器里的 AI 插件、命令行工具、甚至你自己写的小脚本都通过同一个 Base URL 和同一个 Key 去请求模型不用为每个工具单独配一套凭证。接入的核心三件套永远是这三个Base URL、API Key、Model ID。缺一个都调不通。Base URL 填https://taotoken.net/apiAPI Key 在你注册后到控制台的 API Keys 页面生成Model ID 则根据你要用的模型填对应的标识。下面是一个标准的请求示例你可以先用 curl 验证通道是否通curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer 你的API_KEY \ -d { model: 你的Model_ID, messages: [ {role: user, content: 用一句话解释 Chrome 扩展的 manifest.json 是做什么的} ] }如果返回里能看到choices字段和模型输出内容说明通道正常。如果返回 401说明 Key 错了或者没带Bearer前缀如果返回local proxy failed之类的错误通常是网络层或 Base URL 写错检查是不是把/api漏了或者多写了/v1重复路径。对于长期做编码和 Agent 场景的读者可以考虑 Coding Plan它更适合高频调用如果只是想验证某个模型效果用模型对话页面就够了需要管理多个 Key 就去控制台。这几个入口分别是模型对话 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 、Coding Plan https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 、控制台 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 、API Keys https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。接入文档在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到参数问题先查文档。配置好通道后你在写扩展时就可以这样用把 manifest、popup 的代码片段丢给模型让它帮你补全或纠错而不是从零生成。比如你可以问「这是我的 manifest.jsonManifest V3我想加一个点击图标弹出 popup 的功能帮我检查权限和 action 字段是否完整」。这种带上下文的提问比空泛地问「怎么写扩展」有效得多。3. 可复制配置manifest.json 与 popup 完整代码这一节是全文的核心给你可以直接复制、改改就能跑的完整配置。先建一个文件夹比如叫cache-cleaner然后在里面创建下面这些文件。整个扩展的文件结构是这样的cache-cleaner/ ├── manifest.json ├── popup.html ├── popup.js ├── style.css ├── background.js └── icons/ ├── icon-16.png ├── icon-32.png ├── icon-48.png └── icon-128.png图标文件你可以先用任意 PNG 占位尺寸对不上 Chrome 也能加载只是显示会拉伸。重点是 manifest.json这是整个扩展的身份证Manifest V3 的写法如下{ manifest_version: 3, name: Cache Cleaner, version: 1.0.0, description: 一键清理浏览器缓存支持按时间范围清理。, permissions: [browsingData, storage], action: { default_icon: { 16: icons/icon-16.png, 32: icons/icon-32.png, 48: icons/icon-48.png, 128: icons/icon-128.png }, default_popup: popup.html, default_title: 清理缓存 }, background: { service_worker: background.js }, icons: { 16: icons/icon-16.png, 48: icons/icon-48.png, 128: icons/icon-128.png } }注意几个关键点。manifest_version必须是 3写 2 会被 Chrome 拒绝加载。permissions里browsingData是清理缓存必须的storage用来存清理记录。action.default_popup指向 popup.html这是点击图标后弹出的界面。background.service_worker在 V3 里是单个 JS 文件不再是 V2 的数组写法。接下来是 popup.html它定义弹窗的界面结构!DOCTYPE html html langzh-CN head meta charsetutf-8 title清理缓存/title link relstylesheet typetext/css hrefstyle.css /head body h1清理缓存/h1 button idallHistory所有历史记录/button button idpastMonth过去一个月/button button idpastWeek过去一周/button button idpastDay过去一天/button button idpastHour过去一小时/button button idpastMinute过去一分钟/button p idlastCleared/p script srcpopup.js/script /body /htmlpopup.js 负责按钮点击后的实际清理逻辑这里用chrome.browsingData.removeCache按时间戳清理function formatDate(date) { const d new Date(date); const options { year: numeric, month: long, day: numeric, hour: 2-digit, minute: 2-digit }; return d.toLocaleDateString(zh-CN, options); } function showCleared() { const p document.getElementById(lastCleared); p.textContent 已成功清除缓存 formatDate(Date.now()); } function clearSince(since) { chrome.browsingData.removeCache({ since: since }, function () { showCleared(); }); } document.getElementById(allHistory).addEventListener(click, function () { clearSince(0); }); document.getElementById(pastMonth).addEventListener(click, function () { const d new Date(); d.setMonth(d.getMonth() - 1); clearSince(d.getTime()); }); document.getElementById(pastWeek).addEventListener(click, function () { const d new Date(); d.setDate(d.getDate() - 7); clearSince(d.getTime()); }); document.getElementById(pastDay).addEventListener(click, function () { const d new Date(); d.setDate(d.getDate() - 1); clearSince(d.getTime()); }); document.getElementById(pastHour).addEventListener(click, function () { const d new Date(); d.setHours(d.getHours() - 1); clearSince(d.getTime()); }); document.getElementById(pastMinute).addEventListener(click, function () { const d new Date(); d.setMinutes(d.getMinutes() - 1); clearSince(d.getTime()); });style.css 控制弹窗外观宽度建议 320 到 400 像素之间太宽会显得突兀body { width: 360px; padding: 16px; background-color: #f5f5f5; font-family: Arial, Microsoft YaHei, sans-serif; font-size: 14px; color: #333; } h1 { font-size: 20px; text-align: center; margin: 8px 0 16px; } button { display: block; width: 100%; margin-bottom: 8px; padding: 10px; border: none; border-radius: 5px; background-color: #4CAF50; color: #fff; cursor: pointer; } button:hover, button:active { background-color: #333; } #lastCleared { font-weight: bold; margin-top: 12px; text-align: center; }background.js 在 V3 里是 service worker用来处理安装事件和消息最小可用版本如下chrome.runtime.onInstalled.addListener(function () { console.log(Cache Cleaner 已安装); }); chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { console.log(收到消息:, request); sendResponse({ status: ok }); });如果你还想加 content script比如在网页里注入一个按钮需要在 manifest 里加content_scripts字段指定matches和js文件。但注意content script 运行在网页上下文不能直接调chrome.browsingData需要通过chrome.runtime.sendMessage转发给 background 处理。这个边界一定要搞清楚否则你会遇到「权限明明声明了却调不通」的问题。4. 本地加载验证与成功结果确认代码写完后先别急着上架本地加载验证是最关键的一步。打开 Chrome地址栏输入chrome://extensions/回车。右上角有个「开发者模式」开关打开它。这时左上角会出现三个按钮「加载已解压的扩展程序」「打包扩展程序」「更新」。点「加载已解压的扩展程序」选中你那个cache-cleaner文件夹。如果一切正常你会看到扩展卡片出现在页面上显示名称「Cache Cleaner」、版本 1.0.0还有一个「错误」按钮如果没错误它是灰色的。这时候点浏览器工具栏的拼图图标找到 Cache Cleaner点它应该弹出你写的 popup 界面六个按钮整整齐齐。点「过去一小时」如果 popup 底部出现「已成功清除缓存 2025年X月X日 XX:XX」说明整条链路通了。你还可以打开chrome://extensions/里这个扩展的「Service Worker」链接会弹出一个 DevTools 窗口能看到 background.js 里console.log(Cache Cleaner 已安装)的输出。如果加载时报错最常见的是这几种。第一种manifest 里图标路径写错Chrome 会提示「Could not load icon icons/icon-16.png」解决方法是确认文件夹里真有这些文件或者干脆先删掉default_icon和icons字段用默认图标跑通再说。第二种popup 点开是空白多半是 popup.js 里有语法错误右键 popup 界面选「检查」在 Console 里能看到具体报错行。第三种点按钮没反应检查 manifest 的permissions里有没有browsingData漏了它chrome.browsingData就是 undefined。验证通过后你可以用 TaoToken 的模型对话功能把报错信息贴进去问「这个 Chrome 扩展报错是什么意思怎么改」比搜索引擎快很多。模型对话入口在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你在写更复杂的扩展、需要模型持续帮你改代码用 Coding Plan 会更顺手。上架流程也顺带说清楚。本地验证没问题后回到chrome://extensions/点「打包扩展程序」选择你的文件夹Chrome 会生成一个.crx文件和一个.pem私钥文件。私钥一定要保存好后续更新版本要用同一个私钥。然后去 Chrome 开发者后台注册开发者账号需要一次性费用创建新项目上传打包好的 zip注意是 zip 不是 crx填写商店信息、截图、隐私说明提交审核。审核通常几天到两周不等。第一次上架最容易卡在隐私政策说明上因为你的扩展申请了browsingData权限必须在说明里讲清楚「为什么需要这个权限、数据怎么处理」。5. 本篇常见错误排查401、权限、choices 报错这一节把开发过程中真实会撞到的报错集中过一遍每个都给你定位方法和修复动作。第一个调用 TaoToken 时返回 401。完整报错通常是{error:{message:Invalid API key,type:invalid_request_error}}。原因有三个Key 复制时多了空格、请求头没写Authorization: Bearer、或者 Key 已经被删除。修复方法是重新到 API Keys 页面生成一个复制时注意别带上换行。请求头格式必须是Authorization: Bearer sk-xxxxBearer 和 Key 之间有一个空格。第二个返回local proxy failed或连接超时。这通常是 Base URL 写错。正确写法是https://taotoken.net/api如果你在代码里又拼了/v1/chat/completions完整路径就是https://taotoken.net/api/v1/chat/completions。有些人会写成https://taotoken.net/api/v1作为 Base URL然后再拼/v1/chat/completions变成/v1/v1/重复就会失败。检查你的配置里 Base URL 到底填到哪一层。第三个解析响应时报reading choices或Cannot read properties of undefined (reading choices)。这说明你拿到的响应体里没有choices字段多半是请求本身失败了但你的代码直接去读response.choices[0]。正确做法是先判断response.error是否存在再读choices。比如const data await res.json(); if (data.error) { console.error(请求失败:, data.error.message); return; } const content data.choices[0].message.content;第四个Chrome 扩展加载时报Manifest version 2 is deprecated。这是你抄了老教程的 manifest。把manifest_version改成 3同时把background.scripts数组改成background.service_worker单文件browser_action改成action。这三个字段是 V2 到 V3 最常踩的迁移点。第五个OAuth 相关报错比如你在扩展里接了某个需要登录的服务报OAuth2 not granted or revoked。Chrome 扩展做 OAuth 要用chrome.identityAPI并且 manifest 里要声明identity权限和oauth2配置块。如果你只是本地测试建议先用 API Key 方式别一上来就搞 OAuth复杂度高很多。第六个popup 里调chrome.tabs报 undefined。这是因为 popup 上下文里chrome.tabs需要tabs权限而且部分 API 只能在 background 里调。解决办法是把逻辑挪到 background.jspopup 通过chrome.runtime.sendMessage发消息触发。如果你用的是 Cline MCP 或 Claude Code 这类工具来辅助写扩展配置时同样要写全三件套Base URL 填https://taotoken.net/apiAPI Key 填你生成的Model ID 填对应模型标识。Claude Code 的接入文档在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite Codex 的 auth.json 配置也类似把 base_url 和 api_key 填对即可。任何一件套缺失都会导致调用失败。6. 把扩展做成产品从原型到上架的收尾建议跑通原型只是第一步真正让扩展有价值的是把它做成解决具体问题的工具。我拿「翻译扩展」举个例子你可以照着这个思路扩展你的清缓存工具。一个实用的翻译扩展通常需要划词翻译、整页翻译、多翻译服务切换。技术上划词用 content script 监听mouseup事件拿选中文本整页翻译遍历 DOM 节点替换文本多服务切换则在 background 里根据配置调不同 API。这里有个架构上的关键决策content script 负责「读页面、改页面」background 负责「调 API、管配置」popup 负责「给用户操作界面」。三者通过消息通信解耦。你写清缓存扩展时其实已经用到了这个模式只是简单一些。把这个模式吃透你就能做更复杂的扩展。关于用 AI 辅助开发我的经验是把 AI 当成一个「知道很多但需要你给上下文」的结对伙伴。提问时带上你的 manifest 内容、报错信息、期望行为它给的代码质量会高一个档次。用 TaoToken 统一通道的好处是你可以在编辑器插件、命令行、网页对话之间共享同一个 Key 和同一套模型配置不用每换一个工具就重新配一遍。长期做编码和 Agent 场景的话Coding Plan 的额度模型更适合高频调用具体可以看 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后给一个上架前的自查清单manifest 版本是 3、权限声明和实际调用一致、图标文件齐全且路径正确、popup 在本地加载无报错、隐私说明写清楚每个权限的用途、版本号遵循语义化1.0.0 这种。这六项过了审核通过率会高很多。扩展开发不难难的是把每个细节都验证到位而 AI 能帮你加速的正是那些你反复查文档的琐碎环节。