潇大

Apr 24, 2023

ChatTabs: 关于我用 ChatGPT 帮我写浏览器插件这档事儿

用多了浏览器就会有这种感觉,不自觉标签页打开了很多,然后导致页面变得很挤。 为什么不把这些多余的关掉呢?究其原因,
1. 觉得以后还可能会看,就先放在那儿,
2. 担心关闭以后就找不到了,或者要点开它很费劲。
 
由于 web 技术的发展,网页都是通过一串 URL 来定位的,这似乎已经成为了某种“天经地义”的共识。但是,如果我可以通过一个描述来定位到这个网页呢?
我把这个想法问了 GPT,它告诉我可以创建书签、使用自定义标签组、或者是搜索引擎。
notion image
Emm.. 都不咋地,书签是很方便,但是创建起来还是要一些操作,而且书签建多了一样找不到。自定义标签组,其实就相当于把书签建了个文件夹。搜索引擎则更不解决问题了,有些内网或者私密的资料是搜索不到的。
 
所以我决定,可以开发一个浏览器的插件,它有如下基本功能:
  1. 会自动记录你打开过的标签页,把页面的标题和 url 关联起来,并存储到本地(无需人工参与)
  1. 当需要的时候,直接输入要打开的内容描述,就可以从缓存的页面标题中找到最接近的那个,直接打开
这个逻辑听起来也不复杂,但是要怎么做呢。换作以前,听到开发插件这种想法,直接否定三连,因为学习成本太高。但是现在是 AI 时代,思路打法皆有变化,哪怕我是插件小白,有没有可能在 ChatGPT 的辅助下,开发这样一个功能呢?
于是乎,我便踏上了这趟开发之旅。我把这段过程用文字和图片的方式完整记录下来,以供有同样想法的小伙伴参考。

第一次尝试

我写一段最初版本的需求描述,如下。
我想写一个chrome浏览器插件,它的功能是,读取当前打开的标题内容和网址,将这些信息保存下来。用户可以在插件界面下输入标题,这时就会检索到对应的网址,点击确认后打开
当时的想法就是,功能啥的也不期待你能一次性搞定,你告诉我怎么写浏览器插件就好。
结果它回复了一长段话。里面包括怎么样写一个 mannifest.json ,怎么样写一个  popup.html,怎么样写一个  popup.js ,还给出了很详细的代码,乍看很像回事。
这时候,小白的本质就暴露了,因为我不知道如何 “将包含以上文件的文件夹作为一个扩展程序加载到 Chrome 浏览器中” 。
我觉得,这种级别的入门问题就不必劳烦 ChatGPT 了,也担心会扰乱上下文,网上搜个教程应该就能成。
然后我就找到了 https://zhuanlan.zhihu.com/p/151018829 按照上面的操作,成功地把插件安装上去了。
notion image
安装的截图是这样的。 并且还出现了一个插件按钮,点了以后会弹出如下的框。
我大喜过望,想这么快就做完了吗?它直接搞了两个按钮,一个 save 一个 retrive,虽然简陋一些,但至少功能算完整。
notion image
可是,点不动 ... 然后,不知道问题出在哪里 ... 甚至,我都不知道在哪里可以看 log ...
这时候的体验就非常糟糕,经验告诉我说是这段js哪里没调用,但是又看不懂。脑海中飘过若干的假设,我开始怀疑 ChatGPT 是个骗子,生成了一大堆看起来对,然而一点用都没有的东西。
最后 debug 这个功能花了我半个小时时间。因为我按照知乎的教程流程又走了一遍,接着无意中发现了可以看错误日志的地方,最后发现是因为 script 标签放到了 <head> 里,移到 body 最后就好了... (无语中)
Anyway,这下按钮终于可以点击了,而且也能根据输入的 title 自动打开了。

第二轮尝试修改

我在原先对话的上下文后面,继续追问:
修改一下代码,当点击save的时候,自动将所有的标签页的title和url进行保存,无需用户输入框
这时的界面变得更简洁了,只有 Retrive 按钮和输入框,基本满足需求。自动保存功能貌似是在点击插件时触发的。我加了一些日志,确保它是在正常工作的。
notion image

第三轮提示修改

现在这个插件已经可以正常工作了,但显然是有问题的,因为它目前是严格匹配标题,哪怕差一个字就匹配不到。这样的用户体验显然很差。需要再加一个模糊匹配的功能。
模糊匹配也是有很多种方案可选的,这次让 ChatGPT 自己来选择。于是我在原先的对话后面,继续追问:
用户输入的标题,需要与插件中缓存的标题进行模糊匹配,内容最接近的那个链接会打开。同时出于用户体验考虑,在用户输入时,实时展示最匹配的前3个标题
这是它改完后的效果,输入标题后,就会返回最为匹配的前3个结果,然后点击其中之一,就会新打开对应的链接。
notion image
这时候已经可以看到匹配的效果了,AI 写的匹配算法是个贪心算法,会按输入词不断匹配,有优化空间,但已经基本达到效果。
这个时候有个小插曲,AI 在生成提示列表时写了一个 bug,然后我通过一些 debug 的技巧找到了出问题的段落,把有问题的地方指出来让 AI 修复,过程就省略了。如果没有这一步 debug 过程,直接把问题发给 AI,不一定保证能给出解决方案。

第四轮提示修改

这时候,我发现这个插件缺乏一个管理功能,也就是说,我并不知道当前一共有哪些数据在缓存中,于是我在原先的对话后面,又继续追问:
再写一个管理端界面,用户可以看到所有存储在缓存中的标题和url,方便管理
然后它又很高产的返回了好多代码,结构上包括:
  1. 在 popup.html 文件中添加一个链接,该链接用于跳转到管理端页面。
  1. 创建 manager.html 文件,并在其中添加显示所有存储 URL 的功能。
  1. 创建 manager.js 文件,并在其中添加显示所有存储 URL 的逻辑。
  1. 最后在 manager.js  文件中还需要添加一个删除 URL 的功能。
令我有些惊讶的是,它自动补充了删除功能,虽然我在提示中并没有显式地写明要删除,但确实这个功能是需要的。后面有让它按照表格的形式展示,AI 也听话照做了,结果如下:
notion image

第五轮提示修改

这时候,插件功能还是有个小问题,因为只有在点击图标时才会触发保存,但实际使用时不可能每打开一个标签页就点击更新一下。那该怎么做呢?答案就是写一个监听的函数,这个监听函数应该是运行在后台的。
好在之前半个小时的知乎教程没白学,那里面就讲了如何写  background.js 的方法,于是我继续提问:
能否当用户新打开标签页的时候,就触发这个 “保存所有标签页的 URL”,这样中间打开后面又关闭的标签页,也可以一起放到缓存中
AI 回复说,可以使用 chrome.tabs  API 中的 getAllInWindow  方法来获取当前窗口中的所有标签页信息。同时,我们也可以使用用 chrome.tabs  API 的 onCreated  和 onRemoved  事件来监听打开和关闭标签页的操作。
通过监听标签页被创建、被关闭的想法真的很不错。然而我试过之后,就发现事与愿违。
比如吧,我新开一个窗口,打开百度,它只能监听到新的窗口(新建的那个标签页)而不能检测后面的改动。再者,当我关闭窗口时,这个窗口就被关闭了,所以啥也监听不到。(┓( ´∀` )┏)
这很奇怪,我意识到这是我描述需求的方式,并不是解决这个问题的最佳方式,但是 AI 只是按照我描述的去写代码。想通这一点后,我做了些修正:
用户新打开标签页的时候,信息还没加载完,能否当网页加载完毕以后,再触发这个 “保存所有标签页的 URL”呢?修改一下
这下 AI 就听懂了。他说可以使用 chrome.tabs.onUpdated 事件来监听标签页的更新操作,当标签页的加载状态变为 complete 时,再触发保存操作。
并给出了示例代码:
// 监听标签页被更新 chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { if (changeInfo.status === 'complete') { saveTabsToStorage(); } }); // 将所有标签页 URL 保存至缓存 function saveTabsToStorage() { chrome.windows.getCurrent({populate: true}, function(currentWindow) { var urls = {}; for (var i = 0; i < currentWindow.tabs.length; i++) { var tab = currentWindow.tabs[i]; urls[tab.title] = tab.url; } chrome.storage.sync.set(urls, function() { console.log('Saved tabs to storage.'); }); }); }
这个回答就很完美了,实测发现也好用。直到这个时候,我依旧不了解监听标签页的技术细节,但这并不妨碍借助 AI 写成能有效运行的代码。
 

准备发布

搞完这一切,我准备把这个插件发布到 Chrome Web Store 去,在折腾完账号,并且付了5美元的费用以后,我终于来到了资料上传页面。需要填写一大堆的各种说明,就在这个时候,我看到了这行提示:
notion image
好家伙,发个插件还要那么多的步骤工序,填这些信息的时间可能比开发还要长。而且其中一条是,需要用 Manifest V3 的格式发布,而刚才 AI 写的插件是基于 V2 的,这可不行啊,还得改。
这次想来试一下用 PUA 的口吻,让 AI 觉得自己是个资深工程师,我在前面内容的基础上接着说:
你是一个资深的开发工程师,把上面的插件版本升级为基于 Manifest V3 的版本
实际发现,这种 CPU 并没什么用,反而 AI 写出了一些看起来很高级,但其实并没有什么用的代码。比如说,AI 在回复中提到这个插件功能需要用到 scripting,它的作用是允许在任意网站上运行代码。确实这个写法符合你资深开发工程师的地位,然而这种插件写出来肯定也过不了审核的。。
notion image
 
这就告诉我们呢,和 AI 聊天不能花里胡哨。还是要回归朴素。我索性直接新开了一个对话窗口,和它说:
 
帮我把下面的插件清单文件转换成 Manifest V3 的版本。v2 版本如下: <manifest.json>
后面的  <manifest.json> 就是直接把 json 文件给怼上去了,结果其实还不错,AI 回复节选:
notion image
这下给的结果还算靠谱,修修补补以后,也算是可以用了。
到最后提交阶段,还需要软件包介绍以及一些其他的说明,这当然难不倒我了,反正也是用AI写的。
notion image
最后终于整完,提交了审核。也不知道谷歌要审核多久,等过审了会再通知~
 

总结一下

关于我用 ChatGPT 帮我写浏览器插件这档事儿,最早只是起源于一个想法。而从这个想法到实现,断续大概花了我4个小时的时间。其中有大约2小时是在和 ChatGPT 聊天写代码调试,还有2个时间是在捣鼓上传发布插件的东西。这种开发效率在以前是完全无法想象的。
在 AI 来临的世界,一切东西都在加速显化。你拥有什么样的技能、知识,越来越不成为做出这件事情的关键要素,由于集成了世界知识大模型的存在,很多技术上的门槛被抹平了许多。反倒是想法、想法背后的初心,以及你有多么想让这件事发生,变得更加重要。另一种视角下的“心想事成”。
写插件只是一个例子,完全可以用到其他的一些领域。有清晰想法就行动起来,走着走着就知道该去哪儿啦。
 
 

Copyright © 2025 潇大

logo