我从 2005 年开始为 Firefox 构建扩展。我已经集成了书签服务(这让我在 Mozilla 找到了一份工作!),修复了默认主题,增强了开发工具,调整了 Github,优化了性能,简化了标签操作,为所有 Etherpads 添加了书签,修复了 Pocket 以及许多其他 糟糕的奇妙事物。
我已经编写了 XUL 扩展、Jetpacks、Jetpacks(第二种)、SDK 加载项,并且还参与了其中大部分的核心开发。现在我已经见过所有的一切:Firefox 有了 WebExtensions API,一种新的扩展格式,旨在实现浏览器扩展性,而不会牺牲性能和安全性。
在 Firefox 57 中,WebExtensions API 将成为唯一支持的扩展格式。所以现在是时候继续前进了。我不能再沉迷于旧扩展格式允许的不安全的性能漏洞 API 的奢华中。是时候迁移我无法忍受没有的扩展了。
我从 Always Right 开始,这是我最常用的浏览器扩展之一。我记录了这次迁移,包括 hiccups、失误和折衷方案。希望这能帮助你在扩展迁移之旅中!
我是 Always Right
Always Right 是一个简单的 Firefox 扩展,它将所有新标签立即打开在当前标签的右侧,无论标签是如何打开的。
这很棒,原因有二:
- 标签打开行为可预测 - 它始终保持一致。Firefox 中的默认行为取决于许多因素,过于复杂,这里无法一一列举。我只想说,改变 Firefox 的默认标签打开行为就像在飓风中追逐黄蜂。
-
相关标签分组。当我思考我正在做的事情,并想要开始新的搜索或打开与之相关的标签时,我会打开一个新标签。这个附加组件确保该标签与当前标签分组。默认行为会在标签栏的末尾打开该标签,这会导致两个不同的标签组,它们都与同一任务相关。
从概念上讲,Always Right 是一个简单的扩展,但最终需要完全重写才能迁移到新的 WebExtensions API 格式。大多数重写工作都很轻松且快速,但正如我们作为开发人员所面临的困扰,最后的几部分花费了最长的时间,并且极其令人沮丧。
迁移概述
总体概念没有改变:使用新 API 构建的扩展仍然是一个包含清单文件以及所有代码和资产文件的 zip 文件,就像之前的所有其他扩展格式一样。
迁移的主要部分是:
- 重命名并迁移到新的清单格式。
- 重写代码以使用新的 WebExtensions API。
- 使用新的
web-ext
CLI 工具进行打包。
迁移清单
第一步是迁移你的清单文件,首先将 package.json
重命名为 manifest.json
。
最重要的更改是添加属性 manifest_version
并将其值设置为 2
。有了 manifest_version
、name
和 version
字段,你现在就拥有了有效扩展所需的所有必备属性。其他所有属性都是可选的。
但是,由于你要更新一个已经存在的扩展,因此还需要做几件事。
id
属性对于 addons.mozilla.org (AMO) 来说是必需的,以便将新的加载项与旧的加载项匹配。删除顶层id
字段,并将它的值复制到applications/gecko/id
字段中。-
如果你使用了
main
属性,现在可以通过特定功能来指定你的入口点文件,例如 后台脚本、内容脚本、浏览器操作(工具栏按钮)、页面操作 和 选项 UI。在我的扩展中,我需要监听标签事件,所以我使用了后台属性来加载脚本。 -
permissions
属性被使用,但方式不同。值现在是一个数组而不是一个对象,你拥有的任何值可能不再受支持,需要进行替换。你可以在 MDN 上的 manifest.json 权限页面 上阅读有关支持的权限键和值。
这里没有介绍更多可选字段。阅读 新的 manifest.json 文档 中有关其他字段的信息,以及旧的 package.json 文档。
迁移功能
Always Right 的流程是监听一个事件,该事件指定一个新标签已打开,然后修改该标签的索引,使其位于当前活动标签的右侧。
我首先将我的 /lib/main.js
文件移到 /index.js
,并在 manifest.json
文件中将其指定为后台脚本,如上所述。
然后,我将 /index.js
中的代码从旧的 SDK 标签 API 迁移到 WebExtensions 标签 API。旧的 SDK 代码使用了 tabs.open
事件,而新的代码使用了 WebExtensions tabs.onCreated
事件。
例如,这个:
window.tabs.on('open', function(newTab) {
// do stuff
});
变成了这个:
browser.tabs.onCreated.addListener(function(newTab) {
// do stuff
});
另一个更有趣的转换是如何获取对当前活动标签的访问权限。
在 SDK 中,你可以简单地访问 window.tabs.activeTab
,但在新的扩展世界中,你需要这样做:
browser.tabs.query({currentWindow: true, active: true}).then(function(tabs) {
// do stuff with the active tab
var activeTab = tabs[0];
});
这些是主要更改。应用程序逻辑和代码流与之前几乎相同。但是,由于这是一个具有不同行为的新 API,因此出现了一些问题。我不得不进行以下调整:
- WebExtensions API 代码在活动标签可检索之前初始化,因此我需要添加对活动标签的检查,如果它还不可用,则执行无操作。
-
SDK 标签 API 在用户重新打开之前关闭的标签时不会触发,但 WebExtensions API 会触发。因此我不得不添加检查以确保我不重新定位这些标签。
-
另一个行为变化是,将标签放置在非最后一个固定标签的固定标签旁边会将它放在标签栏的末尾,而不是像 SDK API 所做的那样只将它放在固定标签的末尾。因此现在我获取所有标签并遍历它们,直到找到最后一个固定标签,然后手动将该标签放置在那里。
我还必须提供一些不太理想且目前无法修复的行为:
- WebExtensions API 在标签添加到标签栏后执行
tabs.onCreated
监听器。这意味着,使用 Always Right,如果你有很多标签(比如,数百个),你实际上可以观察到标签被添加到标签栏的末端,然后快速滑到活动标签的右侧。这让人眼花缭乱。 -
使上述问题更加严重的是,标签栏滚动到新标签,因此当前活动标签被滚动到视图之外。
测试和调试
在现有配置文件中进行测试的新的、改进的开发工作流程与 Firefox SDK 完全不同。
要安装你的加载项以进行测试,请打开一个新标签,导航到 about:debugging
(参见下面的屏幕截图)。单击加载临时加载项按钮并选择你扩展源目录中的任何文件。你的扩展将被安装!
但如果你在那里看到错误呢?如果功能没有按预期工作呢?你可以使用浏览器工具箱来调试你的扩展。阅读此处了解如何配置和 打开工具箱。
在开发过程的后期,我发现了 web-ext CLI,它非常棒。像使用 cfx/jpm 一样使用 web-ext run
。它会在临时配置文件中打开。
发布
我的更改完成后并经过测试,我依靠我的新朋友 web-ext
并使用 web-ext build
打包了一个 zip 文件。zip 文件位于 web-ext-artifacts
子目录中,并使用新版本号命名。我像往常一样将文件上传到 addons.mozilla.org,并且扩展通过了验证。我等待不到一天,我的扩展就被审核并上线了!
胜利!好吧,不是完全的胜利:错误马上就来了。在用户们慷慨仁慈地帮助下,他们通过给加载项提供 5 星评级并在评论中指出新版本已损坏的方式来报告了这些错误。😅
我已经修复了大多数已报告的问题,所以我的用户和我都可以在夕阳下快乐地骑马了。
需要帮助?MDN 上有关于迁移加载项的详细文档,请查看 旧扩展移植页面。
你可以在 Github 上的 Always Right 存储库 中查看此加载项的源代码。如果你发现更多错误,请告诉我!
如果你想试用这个扩展,可以从 addons.mozilla.org 安装 Always Right。
参与
所有代码都在不断改进中,参与开发过程并报告错误是解决问题最简单的方法。如果你在 WebExtensions API 中遇到错误,请在 Bugzilla 中的 WebExtensions 组件 中提交错误报告。
我在迁移这个扩展时提交的错误:
-
没有简单的方法来测试扩展在重启后的行为,因为我发现了一些只在 Firefox 启动时才会出现的错误,但是开发扩展会在重启时卸载。
-
Tabs.onCreated
和onRemoved
在不同的时间被评估 – 我在试图找出需要多少个选项卡才能使新选项卡在选项卡栏中重新定位的速度足够慢以至于可以肉眼观察到时发现了这个问题。我的 Tabcount 扩展程序 在这里。 -
Tabs.onCreated
的评估太晚,无法修改索引 – 这是导致选项卡从选项卡栏的末尾重新定位到新位置的错误。 -
需要一种方法来判断新选项卡是否只是以前关闭的选项卡被恢复 – 这个错误对于任何在打开新选项卡的周围执行操作的扩展程序都非常有用。
-
将选项卡移动到一个已固定选项卡的索引会导致选项卡添加到选项卡栏的末尾而不是下一个有效索引 – 是一个“按我的意愿做” API 设计的绝佳机会。
9 条评论