Chrome插件开发
最近一直在开发插件,踩了些坑,这里总结下。
popup程序化弹出?
popup不支持程序化弹出
,曲线解决的方案是,开启新window,打开popup.html
即可。
chrome.windows.create({
url: `popup.html`,
type: 'popup',
height: 640,
width: 357,
left: 100,
top: 100,
focused: true,
})
window resize禁用
const size = [document.body.clientWidth, document.body.clientHeight];
/**
* 禁止修改 popup弹窗大小,new window时无法直接设置禁用resize,因此通过该方法解决
*/
function resizeThrottler() {
window.resizeTo(size[0], size[1]);
}
window.addEventListener('resize', resizeThrottler, false);
消息通讯
chrome extension中资源分三种,popup/content/background,能够与网页直接通讯的是content,因此如果是popup向网页发消息。可以发给content,然后content转发消息给网页即可。
content.js中接收消息使用chrome.runtime.onMessage
,而发送消息给网页使用window.postMessage
chrome.runtime.onMessage.addListener(
(message, sender, sendResponse) => {
window.postMessage(message, '*');
return true;
},
);
popup向content.js发送消息使用chrome.tabs.sendMessage
chrome.tabs.sendMessage(tabId, message);
同时,Chrome也可以接收网页发送过来的消息
网页发送消息给extension使用chrome.runtime.sendMessage
var hasExtension = false;
const extensionId = 'bmkmhpkgcbigmdepppdpdhlifcgoibph';
chrome.runtime.sendMessage(extensionId, {operation: "installCheck"},
function (reply) {
if (reply && reply.data.version) {
hasExtension = true;
} else {
hasExtension = false;
}
});
extension-background接收消息使用chrome.runtime.onMessageExternal.addListene
chrome.runtime.onMessageExternal.addListener((request, sender, sendResponse) => {
})
chrome.runtime返回undefined
网页向拓展发送消息,需要确保设置中externally_connectable
能够命中网页,否则chrome.runtime返回undefined
举个配置例子
"externally_connectable": {
"matches": [
"https://*.19991421.cn",
"http://127.0.0.1/*"
]
}
http://*/*
,https://*/*
无法命中IP地址及localhost域名,因此内网网址这些,需要单独配置,- 端口号不需要考虑,默认都是通配。
- 这里并不建议配置
http://*/*
,https://*/*
,虽然它可行,但浏览器插件中会提示errorWildcard domain patterns such as "http://*/*" are not allowed
popup最大宽高
宽度最大800px,高度最大600px。HTML标签层面会强制给予该大小,如果子标签宽高大于该值,会滚动显示。
推荐尺寸600px高,357px宽
DevTools failed to load source map: Could not load content
Chrome插件只支持inlinemap,因此需要修改构建工具配置,不要使用分离的source map配置,使用比如inline-source-map
hot reload
插件不同于普通的WEB开发,所以热更配置不同,这里推荐使用ExtensionReloader
插件,配置如下
new ExtensionReloader({
port: 9090, // Which port use to create the server
reloadPage: true, // Force the reload of the page also
entries: {
popup: "popup", background: "eventPage", contentScript: "contentScript"
}
})
注意entries中属性值即webpack中entry下配置的入口名,非物理文件路径名。
插件模版-实践
以上这些配置都可以在模版中查看
https://github.com/alanhe421/chrome-extension-react-typescript-boilerplate
插件更新
- 官方商店分发
该方式下,插件会
自动更新
,关于自动更新频率,可能是5小时 - 自行托管分发包
- update_url字段,但方式下,托管的是crx已经签名分发的包,如果是未签名的不行。
- 更新包必须是CRX文件
{
"name": "My extension",
...
"update_url": "http://myhost.com/mytestextension/updates.xml",
...
}
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>
<updatecheck codebase='http://myhost.com/mytestextension/mte_v2.crx' version='2.0' />
</app>
</gupdate>
- 开发包 自定义逻辑实现check,比如popup弹出时提示或者定时器check,有更新推送notification。用户下载新包进行覆盖即可。覆盖后重启浏览器或插件页面手动点击更新
manifest.json配置修改
修改后,浏览器需要重启生效
修改页面window
写在最后
先写到这儿,持续更新