谷歌插件v2升级v3踩坑日记

403 阅读4分钟

一、Manifest V2 即将被弃用

image.png 在今年年初收到v2就要被弃用的通知后,还沉浸在过年喜悦中的心立马紧绷起来。在去年年初的时候就已经有计划升级v3了,但是因为改动太大,而且谷歌后面延迟了v2弃用时间(谷歌原计划是2023年6月弃用),所以升级任务暂时被搁置了。如今已经确认弃用时间,那只能撸起袖子加油干了。

二、Manifest V3 改动点

我们项目用的技术栈是vue2+webpack,下面提到的改动点是我们项目有用到的,没提到的可自行查看官方迁移文档

1、 Manifest.json 文件

1.1 将 manifest_version 字段的值从 2 更改为 3。
{ "manifest_version": 3 }
1.2 更新主机权限

在Manifest V2 中,有两种方法为你的api或任何主机获得权限,要么在 permissions 数组或 optional_permissions 数组。

而 v3 的权限粒度划分会更细腻,不会像之前权限一把梭,所以像主机访问权限配置需要单独添加到 host_permissions 中:

// v2
{
  "permissions": [
    "tabs",
    "bookmarks",
    "https://www.blogger.com/", // 之前主机权限都在 permissions
  ],
  "optional_permissions": [
    "unlimitedStorage",
    "*://*/*",
  ]
}
// v3
{
  "permissions": [
    "tabs",
    "bookmarks"
  ],
  "optional_permissions": [ // 单独配置主机权限
    "unlimitedStorage"
  ],
  "host_permissions": [
    "https://www.blogger.com/",
  ],
  "optional_host_permissions": [// 单独配置主机权限
    "*://*/*",
  ]
}
1.3 替换background字段

在 Manifest V3 中,后台页面被 Service Worker 所取代。下面列出了清单更改。

  • 将 manifest.json 中的 "background.scripts" 替换为 "background.service_worker"。请注意,"service_worker" 字段接受字符串,而不是字符串数组。
  • 从 manifest.json 中移除 "background.persistent"
1.4 更新 web_accessible_resources 字段

web_accessible_resources 用于指定哪些资源文件可以被 web 页面访问和加载,但在 v2 时也是一把梭,基本一次配置哪哪的网页都能访问,同样在 v3 此字段改为资源与匹配的对象形式,看代码就懂了:

// v2
{
  ...
  "web_accessible_resources": [
    "images/*",
    "style/extension.css",
    "script/extension.js"
  ],
  ...
}
// v3
{
  ...
    "web_accessible_resources": [
    {
      "resources": [
        "images/*"
      ],
      "matches": [
        "*://*/*"
      ]
    },
    {
      "resources": [ // 指定资源
        "style/extension.css",
        "script/extension.js"
      ],
      "matches": [ // 谁可以访问
        "https://example.com/*"
      ]
    }
  ],
  ...
}
1.5 合并 browser_action 与 page_action 为 action
// v2
{
  "browser_action": {},
  "page_action": {}
}// v3 直接合并成一个即可
{
  "action": {}
}
1.6 content_security_policy 需要从 string 改为对象配置

content_security_policy 用于定义加载和执行内容的安全策略,在 v3 版本你需要通过对象的形式来做配置:

// v2
"content_security_policy": "script-src 'self' 'unsafe-eval' https://cdn.lr-in-prod.com; object-src 'self'"// v3
"content_security_policy": {
  "extension_pages": "script-src 'self'; object-src 'self'",
  "sandbox": "sandbox allow-same-origin",
  "web_accessible_resources": "https://cdn.lr-in-prod.com"
}

2、background 迁移 Service Worker

这个算是这次升级最大的改动了,已经的很多功能都需要大改甚至部分功能没有替代方案,如加载第三方脚本等。下面将一一列出我们项目需要改动到的地方。

1.1 全面禁止加载远程代码
  1. 之前用webpack打包出来的代码含有eval,需要去掉,处理方法:配置devtool: 'cheap'
  2. 打包出来的代码也含有jsonp,处理方法:将动态引入全部改成静态引入
1.2 禁止所有dom操作(window也无法访问)
  1. 之前Bakcground环境和popup环境中数据通信是直接在Bakcground的window上保存,然后popup通过chrome.extension.getBackgroundPage获取。在v3中需要使用chrome.runtime.onMessage和chrome.runtime.sendMessage进行数据通信,在popup处设置轮询,五秒一次获取一次Bakcground环境数据。
  2. 用chrome.storage代替localstorage,由于chrome.storage是异步的,所有同步获取的逻辑得重构。
  3. 去除第三方包影响,我们项目中引入的一些第三方包里面有用到dom操作,由于没有找到更好的替代包,所以我是直接用webpack插件将源码给修改了
  4. settimeout、setInterval替换成chrome.alarms
1.3 请求方式只能用fetch

我们项目用的是axios,如果替换成fetch的话,改动太大,所以放弃了直接用fetch替换。最后想到的是用为axios增加一个fetch Adapter,这样可以在代码不用更改的情况下,所有请求逻辑走到最新的fetch请求里。这里需要注意fetch的中断需要用AbortController

1.4 webpack热更新魔改

chrome.runtime.getPackageDirectoryEntry在serviceworker里已被弃用,之前的hot-reload文件已失效。现自己实现一个hot-reload,原理:用node启一个websocket服务器,监听dist目录文件变化,serviceworker监听ws通知实现重载。以上功能集成到webpack插件里,在开发环境时运行

1.5 谷歌api替换

最后一步,把所有api替换完,就搞定啦!

3、总结

由于国内关于谷歌插件v2迁移v3的文章稀少,而谷歌自身文档写的也一眼难尽,所以升级过程中踩了许多坑。但总算也是升级完拉。

4、参考文献

developer.chrome.com/docs/extens…
zhuanlan.zhihu.com/p/660467026