分类
扩展

Chrome 扩展大升级 Manifest V3:变化

上一篇博客 聊了聊 Manifest V3 的设计思路,接下来就该详细介绍下这个版本的变化。按照 官方介绍,V3 的变化主要有以下五点:

  1. 需使用 Service worker 替换 background scripts/pages。这个变化对我影响很大,未来开发新扩展的时候,需要使用全新的代码架构;老扩展要升级,多半也要彻底重构。
  2. 修改网络请求的 API 换作 chrome.declarativeNetRequest。这个变化我暂时没用到,将来有机会再说。
  3. 禁止运行远程代码,所有将会运行的代码都必须事先打包进扩展,接受商店的审查。这点对我厂的影响非常大,很可能我厂的 Showman 要彻底改变实现方式——最大的可能就是停留在 Manifest V2,如果 Manifest V2 被废弃,那就使用新技术栈开发下一代产品。
  4. API 全部提供 Promise。这是应该的,小改善。
  5. 其它一大批杂七杂八的功能变化。

其中 2 暂时不好评价,3 只能被动接受,4、5没啥好说的,所以接下来谈谈 1,background script => service worker。

Background Scripts/Pages

Background scripts/pages(后面简称 background script)的地位很重要,是浏览器扩展的重要组成部分,可以作为联系其它组件的中心、主控,在扩展功能复杂时,作用很大。比如我厂的 Showman,既需要用 content script 注入功能到目标网页,也需要单独打开页面让用户交互,这里每个 JS 都要跑在独立环境,彼此隔离,所以就需要有一个中控,一方面连接各个独立的组件,另一方面常驻内存存储一些全局数据。

相信大家不难想到,这种常驻内存的东西,虽然给开发带来了便利,但是也会给内存带来不小的压力。况且,在 Manifest V2 阶段,甚至还支持一个浏览器扩展注册多个 background scripts 和 background pages。每个页面和脚本都要独享一个环境,哪怕只有短短几行代码,于是就会吃掉大量的内存。

Chrome 对内存使用方面的不检点,被大家诟病已久。其开发团队当然也知道,所以最近几个版本 Chrome 都在试图改进这些问题。既然新版本要降低系统要求提高性能表现,尽量节省内存、同时减少运行时间就是必须考虑的事情。所以,新版本扩展规范规定,background script 有且只有一个,而且只能是 service worker。

Service worker 只能注册事件侦听器,不能持续运行。这样一来,就可以让 background script 的执行之间降到最低,并且随需而动,减少内存占用。

Service worker 的特殊用法

1. 事件侦听器都要放在顶层

事件侦听器都要放在顶层,非顶层的事件侦听器会被直接忽略。

2. 使用 storage API 存储持久化状态

不要用全局变量,把一些需要用到的数据都放到 storage 里,如下:

// 不要这样做
const foo = 'bar'
chrome.runtime.onMessage.addListener(({ type, name }) => {
  if (type === "set-name") {
    name = foo;
  }
});

// 这样做
chrome.runtime.onMessage.addListener(({ type, name }) => {
  const foo = await chrome.storage.local.get(['name']);
  if (type === "set-name") {
    name = foo.name || 'bar';
  }
});

3. 使用 chrome.alarms 取代定时器

我们以前一般习惯于用 setTimeoutsetInterval 定时执行,但它们在 service worker 里都会失效。此时,要用专门的 Alarms API 代替,使用方法倒也不难:

chrome.alarms.create({ delayInMinutes: 3 });
chrome.alarms.onAlarm.addListener(() => {
  // do something
});

需要注意的是,content script 里虽然仍支持 setTimeout,但是太长的定时器会被直接忽略掉,时间阈值是 13s,即短于这个时间的仍然会触发,但是超过的会被忽略。建议如果 content script 需要定时器,那么也交给 background script 来做。

4. 其它一些常见场景的处理

包括解析 HTML/XML、处理音视频播放、使用 <canvas> 绘图等,因为我暂时都没用到,所以就先不说了。

分类
扩展

Chrome 扩展大升级 Manifest V3:设计原则

Chrome 前阵子发布了 Chrome Extension Manifest V3 规范,算是为浏览器扩展开发的下一步明确了方向。虽然目前只在 Chrome 浏览器里有效,不过鉴于 Chrome 的统治级地位,相信只要不出大问题,将来肯定会成为 Browser Extension 规范——实际上,Browser Extension API 就约等于 Chrome Extension Manifest V2。

我最近一两年的工作大多围绕浏览器扩展展开,所以对这个规范很关注,近期也研读了不少,准备写几篇博客分享一下。这是第一篇,主要分享下 MV3 规范的设计原则。


1. 保护隐私

最初的浏览器扩展给了开发者非常大的自由,可以让浏览器扩展大大加强浏览器的能力,但是也会给普通用户带来大量数据外泄的风险。

新规范支持浏览器扩展在不需要特殊权限的时候先正常运行,有用到某个权限的时候,再向用户请求使用许可。另外,权限的授予也不再是永久的,避免长期授权可能导致的问题。

2. 保障安全

扩展要上商店,必须经过审核,很多功能可能没那么容易过审。于是很多应用开发者都会想方设法使用外部资源来绕开平台对应用的监管,这样做能带来更强大的功能,也会带来更大的隐患。比如我厂,Showman 必须用外部 JS 才能驱动网页;但如果是恶意开发者,他们可能会利用这点干坏事。

对于外部资源的使用,新规范采用了更严格的限制。V3 里,只能使用静态外部资源,比如图片视频等,外部脚本彻底不能跑了。这对我厂 Showman 是不利消息。

3. 提高性能

Chrome 的性能一直被人诟病,内存杀手的恶名背负已久。可能很多人不知道,其实 Chrome 扩展架构一直是个大问题。出于安全考虑,扩展里的 JS 会运行在很多不同环境下,比如 content script,background script,都会跑在独立的沙箱里,也就是说,哪怕你一个页面都不开,可能也有好几个扩展 background page/script 在悄悄运行,占用你的内存。

所以新版本也作出改进,强制限制只能使用一个 background script,而且这个 background script 必须以 service worker 形式来跑。保证浏览器扩展不会吞噬掉所有系统资源。

4. 追随统一的 Web 平台

以前为了提供更强大的功能,给扩展增添了很多专享 API,比如文件读写。如今 Web 平台不断发展,一些经过验证的 API 被吸纳到 Web 标准,一些步子太大的 API 被证明其实没啥用。总之,为了让降低开发者的心智负担,也让更多的代码可以一次开发导出运行,新规范会尽量向 Web 平台靠拢,减少专享 API,鼓励使用 Web API。

5. 改善功能

当然,说到底,大家之所以用浏览器扩展,还是因为它的功能比 Web 强。所以新版本还会继续探索新的可能性,让扩展平台更强大、功能更丰富,以便给用户带来更大的价值。

总结

MV2 已经过去了大约十年,确实有一些不合时宜之处,各个平台也逐步摸索了一些更好的策略,比如,权限和安全性的改进很明显是从 iOS、Android 学习而来。至于性能表现,我也很期待。

以上内容主要来自于我对新老 API 的理解和这篇官方介绍:Extensions platform vision – Chrome Developers。推荐阅读。

分类
扩展

Chrome 扩展在页面执行 JS

基于安全考虑,Chrome 扩展运行在一个独立的沙箱里,不能直接接触页面里的变量和实例。但有些时候我们必须在当前页面的环境里执行 JS,比如近期开发 Navlang 时遇到一个需求:修改浏览器环境里语言信息,实现语言切换。