记一次浏览器插件开发经历
最近做了一个浏览器插件的项目,私以为还是比较有意思的,在此记录一下经历。
这个浏览器插件的主要功能是,提供一个拨号盘界面,可以进行呼入、呼出的功能。再额外添加一些围绕着呼叫的辅助功能,比如:联络记录,通讯录,弹屏等等。
WXT 介绍
为了提高开发效率,我直接查找了可以用的插件开发框架,经过一番搜索最终选择了 WXT。
它可以使用流行的前端框架进行开发,它是建立在 Nuxt之上的,而我对 Vue 还算比较熟悉,也就选择了 Vue 这条技术路线一路到底。
即使现在看来,整个开发过程的体验还是很轻松加愉快的。不足之处是,说明文档不是很全,有很多待补充内容,如果找不到想要的内容,只能到 issues 中寻找。
打开 WXT 的官方网站,找到 Get Stared,初始化项目,
1 | pnpm dlx wxt@latest init <project-name> |
命令执行完成之后,会生成一些模板代码,具体有什么用可以到官网查看 Link 。
WXT 遵循的是 约定优于配置,每个目录内的文件在最终编译时会转换为对应的文件。
例如:components 内的文件会转换为组件,background 内的文件会转为 ServiceWorker,*.content.ts 会转为 content scripts。
如果熟悉 Nuxt 的话,composables, hooks, utils 内的文件可以自动导入。像是在使用全局的函数,用起来很方便。
插件内的概念
在开始动手之前,需要先了解一下浏览器插件的概念,有助于开发。
popup
popup 是用户点击插件图标时,弹出的窗口。这个窗口有大小限制,为 800x600。
这个窗口内的内容,可以理解为就是html。框架内编写的vue组件是在这里渲染的。对应 WXT 的 entrypoints 目录中的 vue 文件。
每次打开 popup 时,vue代码都会重新加载。如果想实现一些状态共享的功能,在 popup 关闭时,状态都会清空,所以需要存到 storage (后面讲)中在打开时再次读取。
background scripts
background scripts 是在浏览器后台运行的脚本。在 manifest v3 中,backgound scripts 就是 service worker.
对应 WXT 的 entrypoints/background 目录中的文件。
background scripts 不受跨域影响,可以监听来自 popup 和 content scripts 的消息。
content scripts
content scripts 是在浏览器页面中运行的脚本。在页面加载后会注入到页面中。可以操作 DOM 元素。
storage
storage 用来存储数据。类似 localStorage,使用时必须加上前缀,local:、session:、sync: 和 managed:。
与 localStorage 不同,storage 可以监听值的变化,也可以存储对象值。
storage 的数据可以在 popup,background scripts 和 content scripts 之间共享。
我把它当作 Redis 来用,暂时没发现姿势有什么不对劲。
message
message 用来在 popup,background scripts 和 content scripts 之间传递消息。
主要用法为
1 | // 接受消息 |
插件功能介绍
插件通话功能是由 jssip 实现的。页面上实现了登录注册,指定好后端地址,就可以使用通话功能了。
插件的页面组件使用了 vant.
拨号盘和话务功能
这部分我使用 vue 画了一个拨号盘的界面用于用户交互。话务功能 jssip 中有现成的函数,可以拨号,挂断,静音等,直接调用相关函数就可以了。
拨号盘界面需要注意的是,要根据不同的话机状态,显示不同的样式。
因为 jssip 要获取用户媒体和创建 Audio 用于播放铃声,这部分代码只能放到 content scripts 脚本中。
个人暂时觉得还是不太完善,在网上查资料可以有 offscreen.html 和 background.html 的其他方法,暂未成功。
popup 中的状态,在用户关闭后就会丢失,而且这个窗口很容易被关闭。每次打开时都需要从 content scripts 中同步状态,这也就用到了 storage 和 message。
来电通知使用了 notifications,如下代码。这一部分倒是没遇到什么问题,jssip 收到来电后,使用 message 发到 background scripts 就可以了。
1 | browser.notifications.create({ |
为了加强插件状态的直观性,在通话和来电时改变图标,可以使用
1 | browser.action.setIcon({}); |
除了 jssip 的 websocket 外,插件还需要一个新的 websocket 获取后台系统的消息,以实现弹屏功能。这一部分也放到了 content scripts 脚本中,暂时没遇到什么坑,轻松加愉快。
通讯录
通讯录可以直接使用 vant 内的组件和 storage 来实现。
在使用 storage 存储的时候需要注意,数据是插件内全部可见的。也就是即使我这个插件需要不同的用户先登录后再使用,如果用户A保存了通讯录,用户B登录后也能访问到。
所以在保存这些数据时,需要给数据打上标记,让用户只能访问自己建立的数据。
弹屏功能
弹屏功能是收到来电后,可以打开指定的网页内容。网页可以由用户自行填写,支持内容替换。这样在和其他CRM系统集成的时候,可以方便的调用第三方系统内的功能。
这一部分也比较简单,使用 message 然后在 background scripts 脚本中处理。
1 | chrome.tabs.create({ url }); |
国际化
这一部分使用了 vueI18n
可以参照 WXT 的示例
没有遇到什么坑点,唯一要注意的是,在 background scripts 中,要这么用
1 | i18n.global.t('', {}, { locale: 'en' }); |
界面截图
总结
经过这个项目,我熟悉了浏览器插件的开发流程和概念。
幸好用了框架,没有让代码乱成一锅粥。
vue 生态中的资源也能很好的利用上。我想如果后续迭代的话,也很方便快捷。
——————
本文为个人原创,转载请署名且注明出处。