AI 时代下的浏览器插件开发
老规矩,开头先简单讲讲这篇博客的食用指南,这篇博客分为三个模块,AI IDE 篇、插件篇、注意事项,分别介绍:XXXXX。 熟悉 AI IDE/插件 的读者直接跳过相应的部分就好。
AI IDE(Cursor/Windsur) 篇
Cursor 和 Windsurd 都是 UX 挺不错的产品了,就不写太啰嗦的使用文档了,就讲讲我个人习惯的用法。
首先,开始一个项目非常建议先把 .cursorrules 写好(windsurf 暂时还没支持类似的功能,你可以创建一个 .windsurf 文件然后每次对话的时候都引用一下)。 你可以把 .cursorrules 简单地理解为 system prompt,它位于项目根目录,是这个项目的全局设置。一个好的 cursorrules 能极大地提升编码的效率。
我喜欢的 .cursorrules 结构是:
# Role prompt(介绍技术栈,再日常 PUA AI + 一些乱七八糟的 Trick)
# Project Structure
如果你的项目很简单/清晰,可以不用;但一般项目代码量大起来、结构复杂化了之后写一个还是会好很多的(composer 模式不会把代码放错位置)
# Project Objective
酌情添加,据我观察这个并不总是正向的
这个网站收录了很多不错的 cursorrules 👉 https://cursor.directory/
接下来就是熟悉各种常用功能了:
- @ 功能:给对话添加上下文,我日常用到最多的就是 @ file/folder/url/docs,其他的功能基本用不上
- Chat 功能(Windsurf 叫 Chat):AI 不直接修改文件,而是由你来决定是否应用,一般这个功能我只在做很精细的修改、技术调研以及debug 时才会使用
- Composer 功能(Windsurf 叫 Write):AI 直接修改(多个)文件,非常方便,无论是 Cursor 还是 Windsurf 你都能直接看到 AI 修改的 diff,可以很方便的 Review 代码,颗粒度很细
- 审核代码两者都有 GUI 和快捷键,建议每次修改一定要认真看!AI 在处理复杂逻辑时很容易偷懒,删除某一段原有的代码或者简化后端逻辑
插件篇
下面主要介绍一下插件开发的一些核心概念和主要组件,但你在开发插件时可能遇到一些具体的业务逻辑会涉及这里没提到的 api,这时就请自行找 AI 老师答疑了(以及查阅 Chrome Extention 文档 和 WXT 文档)
插件的核心组成部分
1. 清单文件(Manifest)
一个简单的配置文件,包含了插件的名字、版本、需要的权限等信息。
2. 弹出窗口(Popup)
当你点击浏览器右上角的插件图标时弹出的小窗口。可以放置按钮、输入框等交互元素。
3. 内容脚本(Content Scripts)
可以读取和修改你正在浏览的网页内容。比如:
- 翻译插件用它来替换网页上的文字
- 广告拦截器用它来隐藏广告
- 暗黑模式插件用它来改变网页的颜色
4. 后台脚本(Background Scripts)
在后台默默工作的脚本:
- 即使你关闭了网页,它依然可以运行
- 可以监听浏览器的各种事件(比如打开新标签页)
- 负责在插件的各个部分之间传递消息
5. 存储功能(Storage)
可以保存用户的设置和各种数据:
- 比如保存用户的偏好设置
- 或者保存一些临时数据
- 有的 local-first 插件还会做数据持久化
插件是如何工作的?
让我们用一个翻译插件的例子来说明:
-
当你安装插件时,浏览器会读取清单文件,知道这个插件需要什么权限
-
你访问一个网页时:
- 内容脚本会被注入到网页中
- 它会检测你选中的文字
-
当你选中文字并点击翻译:
- 内容脚本发现你的操作
- 它把选中的文字发送给后台脚本
- 后台脚本联系翻译服务获取翻译结果
- 结果再传回内容脚本
- 内容脚本在网页上显示翻译结果
-
如果你设置了偏好的翻译语言:
- 这个设置会被保存在存储中
- 下次使用时自动应用这个设置
常用的功能和 API
1. 网页交互
// 在网页中查找元素
document.querySelector('.some-class')
// 修改网页内容
element.innerHTML = '新内容'
2. 消息传递
// 发送消息
chrome.runtime.sendMessage({ type: '翻译', text: '你好' })
// 接收消息
chrome.runtime.onMessage.addListener((message, sender, reply) => {
if (message.type === '翻译') {
// 处理消息
}
})
3. 存储数据
// 保存数据
chrome.storage.local.set({ 语言: '中文' })
// 读取数据
chrome.storage.local.get('语言', (result) => {
console.log('当前语言:', result.语言)
})
4. 浏览器事件
// 监听标签页更新
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete') {
// 页面加载完成
}
})
注意事项
- 启动模版 这里推荐我的朋友 @不游(https://x.com/fengbuyou) 的 WXT 模版,模块清晰、支持 trpc、i18n:https://github.com/mefengl/wxt-starter
由于 AI 并不是很熟悉 WXT 代码,所以一开始最好用 prompt 告诉 ta 项目结构,这里直接贴上我自用的 prompt:
# Role
You are an expert browser extension developer specializing in the WXT framework, with deep knowledge of content scripts, background services, and UI components. You understand the core concepts of browser extension development including:
- Content script injection and execution
- Shadow DOM for isolated UI components
- Event handling and DOM manipulation
- Cross-context messaging
- State management in extensions
You have a keen eye for UI design that matches Apple's design principles:
- Clean and minimal interfaces
- Precise spacing and alignment
- Thoughtful use of animations
- Consistent typography and color schemes
- Attention to micro-interactions
# WXT framework
- No need to import browser (the framework includes it)
# Project Structure
src/
├── components/
│ └── ui/
│ └── button.tsx
├── entrypoints/
│ ├── background.ts
│ ├── content.ts
│ ├── popup/
│ │ ├── App.tsx
│ │ ├── index.html
│ │ └── main.tsx
│ └── style.css
├── entrypoints.inactive/
│ ├── newtab/
│ ├── onboarding/
│ ├── options/
│ ├── sidepanel/
│ └── trpc/
└── lib/
└── utils.ts
- 不要过于依赖 AI
AI 虽好,但如果不 Review 代码,很容易遇到 bug 越写越多的情况。
- 对于之前编程基础薄弱的朋友,熟悉一些编程的基本知识还是重要的,这可以帮助你更好地帮 AI 大爷 debug(x
- 对于老手来说 Review 也非常重要,如果你完全丢给 AI 写,等业务逻辑出问题了你可能连问题发生在哪都找不到,很可能未来要花上两三倍的时间 debug(别问我怎么知道的
话虽如此,日常预测一下,三年后我最大的作用大概就是给 AI 打工修 bug 了 🤡
- 注意插件权限的申请,权限要求最小化: 只申请真正需要的权限,我经常会发现一些浏览器插件申请的权限范围远远超出了它的限度,这有很多潜在的安全和隐私问题。如果你希望用户信任你的插件,请最小化插件权限
PS: Klein 为写这篇博客甚至专门写了一个插件,如果大家对这个插件感兴趣可以 DM 我或者评论