使用 CRXJS Vite 插件开发 ChatGPT SidePanel 插件(一)

OpenAI DevDay 简单回顾

OpenAI DevDay 上发布了一大堆新特性新功能,提升上下文容量、降低 token 价格,再次震撼整个行业。相信大家已经通过各种渠道了解到这次更新的细节,所以我就不再赘述。这里简单分享三个观点:

  1. 这次更新最值得关注是 Assistant API,因为这项功能大大降低了 AI 工具的开发门槛,让很多开发者不需要学习了解新技术,就能上手开发较复杂的 AI 应用。
  2. TTS、DALL-E 3 API 开放后,OpenAI 开发生态基本完整。ChatGPT 可以开口说话,也可以动手画画;再加上前面说的 Assistant API 所带来的 Retrieval 和 Code Interpreter,ChatGPT 可以拥有训练集以外的知识,也可以拥有 LLM 以外的逻辑思维能力。产品实现上的卡点基本打通,剩下就是应用层开发扩展了。
  3. $20/月的 ChatGPT Plus 价值进一步提升,俨然已经是性价比之选。如何好好利用,将其价值压榨出来,值得我们思考。我的想法是通过浏览器扩展加强自动化与可编程性。

Chrome Extension SidePanel API (Chrome 114+)

Chrome 浏览器从 v114 之后,开始支持 SidePanel,从此我们可以把扩展放在浏览器侧边栏里,提供新的可能性。

之前我们使用扩展时,有三种方案,它们都有一些影响使用的问题:

  1. Popup:非常容易被关闭,基本上只要 popup 窗体失焦,就会被关闭,里面执行中的程序也会停下来。
  2. Content Script 插入 DOM:新插入的 DOM 可能跟原本的页面有冲突,尤其是样式,会增加开发成本。
  3. 独立打开:需要成为 activeTab,无法与目标页面共存。

这些问题都可以被 SidePanel 很好地解决。于是,我们可以利用 SidePanel API 开发一个浏览器扩展,它可以大幅加强某个网站的功能、提升在这个网站里执行自动化操作的能力。我们不用担心它会被以外关闭,导致自动化失效;也不用担心它会和目标网页产生冲突。

假如,我们针对 ChatGPT 网站开发一个扩展,加强它的功能,把 ChatGPT Plus 的功能和额度用好用满,应该可以实现一些相当不错的功能。

CRXJS Vite 插件改进浏览器扩展开发

产生上述想法之后,我就一直想找机会试试。不过开发浏览器扩展还有个痛点:扩展拥有加强版 API,在普通页面里无法使用;但是如果使用开发者模式加载扩展,又会丧失 HMR,开发不便。

经过调研,发现 CRXJS Vite 插件 可以解决这个问题。它可以给插件开发环境添加 自动更新的功能,我们就不需要每次更改代码之后再手动刷新,也可以确保我们的开发环境支持全套 chrome.* API,与实际运行环境一致,大大提升我们的开发效率。

使用该插件的方式非常简单。首先,创建一个 vite 项目。对我来说,效率最高的框架还是 Vue3。本着每次尝试的新技术不要超过 1/4 的比例,那就 vue-ts 吧:

pnpm create vite my-vue-app --template vue-ts

接下来,安装并配置 crxjs vite 插件:

pnpm i @crxjs/vite-plugin@beta -D

然后配置 vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.config';

export default defineConfig({
  plugins: [
    vue(),
    crx({ manifest }),
  ],
  // 注意,这段配置很关键,请保证开发端口与 hmr 端口一致。不知道为何,插件生成的扩展里缺少 5173 默认值。
  server: {
    strictPort: true,
    port: 5173,
    hmr: {
      clientPort: 5173
    },
  },
})

我的 manifest.json 也是使用 TypeScript 生成的,所以上面我 import 本地的 manifest.config.ts 文件。

export default defineManifest(async function (env) {
  return {
    "manifest_version": 3,
    "name": "my ChatGPT tools",
    permissions: [
      'activeTab', // 要往目标页注入脚本
      'scripting',  // 同上
      'sidePanel',  // 启用 sidePanel
      'tabs', // 为了与 content script 通信
    ],
    content_scripts: [
      {
        matches: ['https://chat.openai.com/*'],
        // crxjs 会帮我们把目标文件编译后注入目标页面
        js: ['./content/src/index.ts'],
      },
    ],
    // 针对 ChatGPT 而做
    host_permissions: [
      'https://chat.openai.com/*',
    ],
    // 启动 sidePanel 时,加载当前项目的页面
    side_panel: {
      default_path: 'index.html',
    },
    // 这里主要为了点击图标能打开或关闭 sidePanel,background script 同样交给 crxjs 处理
    background: {
      'service_worker': 'src/sw.ts',
      'type': 'module'
    },
  };
});

配置完成之后,照常启动项目 pnpm run dev

然后在浏览器的扩展管理器里启动开发者模式,加载已解压的扩展目录即可。

CRXJS 插件原理

启动开发环境之后,CRXJS 会帮我们生成一个开发版的浏览器扩展,里面除了必备文件之外,还有各大组件所需的加载器,帮我们分别加载 service worker、content script,和页面内 js。它还会建立一个 WebSocket 连接到 vite 开发服务器,当侦听到目标文件出现变化时,就通过各种方式重新加载。比如,页面文件可以直接 HMR,service worker 可能要刷新组件,而 content script 甚至要刷新目标页。

于是,便实现了浏览器扩展在开发环境下的 HMR。

使用 CRXJS 开发浏览器扩展的注意事项

首先,前面代码里有写,需要注意配置 HMR 端口。不知道为何,CRXJS 不使用默认的 5173 端口。

其次,content script 需要在目标页面执行,所以 content script 修改后,常常需要刷新目标页。但是不知道什么原因,有时候 CRXJS 自动刷新目标页之后,content script 并没有更新,我猜测与这几步操作的执行顺序有关。我建议用开发者工具打开 content script 确认一眼。

比如我的 content script 是 content/src/index.ts,那么就确认 content/src/index.ts.js 即可。

以及,由于 HMR 可能会更新运行环境,如果此时恰逢我们在使用 chrome.tabs.sendMessage() 传递消息,可能导致 SidePanel 页和目标页连接断开,消息传送失败。解决方案嘛,就是多重启。修改完消息两端的代码之后,连目标页带侧边栏一起重启一次,即可。

总结

目前我的扩展还在开发中,将来做好了可能会上线 CWS,暂时就先不公开仓库了。

新技术总能带来新的可能性,希望大家都能抓住这一波机会,无论是 OpenAI、LLM 还是浏览器 SidePanel 扩展,做出有价值的产品。

有任何问题、建议、想法,欢迎留言讨论,共同进步。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据