让 WebExtension 插上 npm 的翅膀

让 WebExtension 插上 npm 的翅膀

让 WebExtension 插上 npm 的翅膀

我一直在维护两个扩展,一个叫 xStyle,一个叫 Header Editor。如果你做过 Firefox 插件并且提交到 Mozilla Addons 上了,那么你也应该会和我有相同的感受:Mozilla 真烦。Mozilla 会不断要求你提供各种第三方组件的源代码之类的。如果是你自己修改过的版本,还要求提供修改说明。在 xStyle 中,我打包 stylelint 的时候修改了一些东西,打包后就把原来的东西删掉了。所以 Mozilla 三番五次找我要,我也没办法提供。

其实 Mozilla 也是烦,查来查去也不一定能保证扩展不作恶,一大堆琐事反而影响了开发者。

另一方面,我一直是将第三方库直接包含到代码仓库里的。这样一来,管理起来就比较麻烦,也很浪费代码仓库。另外我也一直想用 Vue 编写页面。所以经过挑选后,我决定用 webpack 来打包 WebExtension。

准备:一些基本组件

为了方便使用,我已经把基本元素放到了 GitHub 上:FirefoxBar/WebExension-Template

把这个项目 clone 下来,然后使用 yarn 或 npm 安装好。然后?然后就可以愉快的开始了。

开发与调试

运行yarn watch:dev便进入了开发模式。webpack 会自动将源码编译后放到 dist 下。当观察到源码有修改时,会自动编译并重载浏览器中的扩展。

需要使用 npm 上的库,也十分简单,例如使用一个名为 uuid 的库:

  • 用 npm 或 yarn 安装它:yarn add uuidnpm i uuid

  • 按照项目说明,在你的 Vue 页面的 script 部分,或 JS 代码中引入:

import uuidv3 from 'uuid/v3';

console.log(uuidv3('http://example.com/hello', uuidv3.URL));

在打包的时候,webpack 会自动分析依赖,然后将你实际用到的内容打包进来。其他的开发与原本的网页、扩展开发一般无二。

页面

项目本身内置了两个页面和一个 background。如果需要增加、删除、修改,可以看下面的方法。

增加

如果需要增加页面,将代码中的 options 文件夹或 popup 文件夹复制一份,然后修改 webpack.config.js:

	entry: {
		'popup/popup': './popup/popup.js',
		'options/options': './options/options.js'
		//将你的页面加到这里
		'page/page': './page/page.js'
	},

再修改一下 scripts/remove-evals.js:

const bundles = [
	'options/options.js',
	'popup/popup.js',
	//将你的页面加到这里
	'page/page.js',
];

重新启动编译,你的页面就自动生成出来了。需要增加脚本的与上面方法类似,不同的是,只需要复制单个 js,不需要复制整个文件夹即可。

删除

以去掉 popup 为例,修改 webpack.config.js:

	entry: {
		'options/options': './options/options.js'
	},

再修改一下 scripts/remove-evals.js:

const bundles = [
	'options/options.js'
];

如果 manifest.json 里面有使用,也一并删除。最后把相关文件删除。

打包和发布

先打包生成代码:运行yarn build就可以在 dist 目录下生成最终代码。

另外,为了方便发布扩展,还有四个命令,分别可以发布到 AMO、Chrome WebStore、AMO 仅签名、crx。使用需要安装 zip,Linux 下直接通过包管理安装,Windows 下使用 GnuWin32 中的 zip 工具。下面一一介绍:

AMO 和 AMO 仅签名

新建一个 JSON:encrypt/amo.json,内容为你的 amo 密钥。注意不要把这个文件提交到 Git 上:

{
	"key": "user:xxxxxx:xxx",
	"secret": "xxxxxxxxxxxxxxxxxxxxxxxxx"
}

在 package.json 中配置你的扩展 ID 和最低版本:

"webextension": {
	"firefox": {
		"version": "52.0", //最低浏览器版本
		"xpi": "headereditor@addon.firefoxcn.net", //仅签名版本的扩展ID
		"amo": "headereditor-amo@addon.firefoxcn.net", //发布到AMO版本的扩展ID
		"update": "https://ext.firefoxcn.net/headereditor/install/update.json" //用于仅签名的自分发版本的自动升级
	}
}

最后,执行yarn pack:amo即可自动发布到 AMO。或使用yarn pack:xpi自动签名。最后生成的签名版本将会存放到 dist-pack 目录下。

Chrome WebStore

首先安装本向导,获取 clientId、clientSecret 和 refreshToken,然后新建 encrypt/cws.json,内容如下。注意不要把这个文件提交到 Git 上:

{
	"id": "你的clientId",
	"secret": "你的clientSecret",
	"token": "你的refreshToken"
}

在 package.json 中配置你的扩展 ID:

"webextension": {
	"chrome": {
		"id": "eningockdidmgiojffjmkdblpjocbhgh" //扩展ID
	}
}

最后,执行yarn pack:cws即可自动发布到 Chrome WebStore

Crx

在 package.json 中配置你的自动更新地址:

"webextension": {
	"chrome": {
		"update": "https://ext.firefoxcn.net/headereditor/install/update.xml"
	}
}

然后将密钥文件(pem)放在 encrypt/crx.pem 下,执行yarn pack:crx,稍候片刻,生成的 crx 版本将会存放到 dist-pack 目录下。

自动发布到 GitHub

除此之外,还支持将 crx、xpi 版本自动发布到 GitHub 的 Release。在 GitHub->Setting->Developer settings->Personal access tokens 中新建一个 token,勾上仓库相关的权限,将它配置到 encrypt/github.json 中,注意不要把这个文件提交到 Git 上:

{
	"token": "你的token"
}

在 package.json 中配置仓库地址:

"repository": {
	"type": "git",
	"url": "https://github.com/FirefoxBar/xStyle.git"
}

最后,在打包完成后,执行yarn release即可将生成的文件发布到与版本名相同的 tag 下。如果这个 tag 已经有 release 了,则脚本不会有任何动作。