Chrome插件踩坑記錄

1,310 阅读5分钟

Chrome插件踩坑記錄

如果平时关注前端技术,就会不时看到关于Chrome插件的博客。多数博客里面介绍了Chrome插件的功能,大致涉及什么API,并且会提供一个小demo。如果你因此好奇而尝试写一个Chrome插件,恭喜你!你会发现里面有不少坑。然后你再去搜索,发现原来也有其他人踩坑,分享了一些心得。尽管不是很多,但每个人所踩的坑都各有不同。

Chrome插件开发的坑可以概括为以下三点:

  1. 糟糕的文档
  2. 缺乏良好的工程化工具
  3. 糟糕的API设计

糟糕的文档

通常,入门时会查看官方文档。当你打开文档时,看到了Chrome插件的功能和架构介绍,然后它展示了三个例子,你看完以为可以开始开发了,可以边看API文档边开发,但接下来你就开始踩坑了。

例如,你想读取DOM上的某些信息,然后想用一些包来处理它们。这个需求够简单了吧,但是只看官方文档是不足以完成这个需求的。首先,在content script上提取DOM信息,之后使用npm install安装依赖包。如果你直接在content script中引入依赖包,就会报错,因为不能直接引入。而且,直接导入包是不行的。别忘了,Chrome插件的文件结构如下:

plugin_structure.png

它以manifest.json为中心。因此,如果想导入包,有两种方法:

  1. 手动将包放入项目中,然后在background或popup中导入。
  2. 使用打包工具(如webpack)进行管理。

这解决了一个问题。接下来需要将信息传递到background或popup。好吧,再次查看文档,查找sendingMessage并进行操作,但没有反应。报错说无法连接,文档中也没有明确的说明。最后终于发现,如果您修改content script,请最好使用 ctrl + shirt + r 进行刷新,否则它不会有反应...

上述的坑点文档是不会说的,或者没有明确说明,这对于新手来说非常不友好。当然,不排除有人会说我水平不够,我也不否认,只是与vscode插件的文档相比,它们真的相差太远了。vscode的插件文档是逐步教学,然后使用不同功能的API来展示不同的示例,非常友好。

缺乏良好的工程化工具

如果想要做规模较大的插件,就自然会用到像vue或react这样的框架。但是官方文档并没有说明如何将这些框架与VSCode结合起来。尽管VSCode有官方的webpack脚手架,但只适用于原生。这个问题目前没有标准解决方案,相关的工程化插件最好不要使用,因为可能会遇到奇怪的问题。我分享我自己的解决方案。

我使用vite + vue作为我的工程化方案。原因是vite的配置简洁,而我已经习惯了使用vue。项目结构如下:

vite_structure.png

manifest.json:

{
  "manifest_version": 3,
  "name": "xxx",
  "version": "0.5.0",
  "action": { 
    "default_popup": "index.html",
    "default_title": "xxx"
   },
  "background": {
      "service_worker": "background.js",
      "type": "module"
  },
  "permissions": ["notifications", "scripting"],
  "content_scripts": [
    {
      "js": ["content.js"],
      "matches": [
        "http://*/*",
        "https://*/*",
        "<all_urls>"
      ]
    }
  ]
}

最后打包的結果如下:

final_structure.png

将除了popup以外的文件都放进public文件夹,vite默认将所有文件都复制到dist中。因此,将所有依赖包的导入都放在popup上。如果background想要导入包,则需要手动将包放入public中引入。需要注意的是,background只能在主文件中进行import,其他js文件的引入是不可以的。也就是说,在manifest文件中,设有background的service_worker,就只能在该service_worker中进行import。而content script则只进行dom或css处理,不引入依赖包。

这种方案的好处是简单,坏处是热更新失效,如果想看到修改结果,就需要重新打包。我目前还没有看到有人有完美的解决方案,希望日后官方可以推出工程化工具来解决这个问题。

糟糕的 API 设计

Chrome 插件的 API 是我见过的最糟糕的 API 设计之一,甚至比微信小程序还要糟糕。难以想象即使在 2023 年,这些 API 仍然没有 Promise 化,仍需要使用回调函数处理。

本部分内容比较零散,我分享一下自己的经验。

Permissions

在 Chrome 插件中,有些 API 的调用需要在 manifest.json 中的 permissions 进行配置。如果你调用了相关功能但没有设置 permissions,插件会返回 undefined 而不是报权限错误,这就很难让人定位错误。

Notifications

要在插件中向用户发送通知,可以使用 Notifications。它的效果如下:

notice.png

它的api:

chrome.notifications.create(
  notificationId?: string,
  options: NotificationOptions,
  callback?: function,
)

如果你想調用通知后, 再次調用是沒有結果的, 因為它是異步的, 但文檔沒有說明…而且的它的api設計挺讓人困惑, 還有一個api是update:

chrome.notifications.update(
  notificationId: string,
  options: NotificationOptions,
  callback?: function,
)

就是通過create返回的id來更新通知, 但也可以用create再做一個。update實在有些雞肋。

Wasm

Chrome插件不支持Wasm。虽然文档没有明确说明,但实践证明无法使用。

Fetch请求

Chrome插件有一个很大的好处,就是在弹出窗口和后台下发出的请求不受跨域限制。