这个前端的小众市场蕴含着巨大财富
Chrome 霸主地位
先看一组数据¹
- 在全球范围内,谷歌浏览器占据了 65.21% 的市场份额。
- 2020 年,约有 26.5 亿互联网用户通过 Chrome 作为主要浏览器访问网络。
- 谷歌浏览器至少有 176,608 个扩展。
具体到chrome插件领域 有大约 50% 的 Chrome 扩展程序的安装量少于 16 次,其中25,540 个(13%)只有一个用户,19,379个(超过 10%)没有用户。 有13个插件的用户量超过1000万,虽然也有一些插件在接近1000万的用户量,但是百万级用户量的插件数量依然不多。在所有插件中近四分之一(24.9%)与生产力有关。 有4.7%的扩展是付费扩展,其中86.4%是一次性付费,插件内支付、月付、年付的比例分别是6.3%,5.7%,1.6%
插件的技术变革
2023年1月后 MV2插件不能再继续更新,MV2插件将不能在Chrome中运行;2023年6月后 即使使用企业策略,MV2扩展程序也不再在 Chrome 中运行。目前已经不能再发布MV2版本的插件,而目前网上的很多文章和资料都是MV2相关的插件教程,相比于MV2,MV3有诸多不同,例如权限控制,API的变动,发起请求的方式等。 插件或多或少大家都用过,但是你有没有想过试着自己做一个浏览器插件,在本篇文章中我将详细讲解chrome插件的现状并手把手教你如何开发一个浏览器插件。 现在正式mv2向mv3过度的时期,机会留给有准备的人,和我一起动手干起来!
可以跳过但是看了能和别人吹的知识
浏览器插件可以理解为运行在浏览器上的app,与手机上的app不同的是它可以控制网页,改变网页结构,修改网页内容,通过安装不同的插件可以帮助用户实现不同的需求。比如屏蔽广告,视频超高倍速快进,查看搜索词SEO竞争激烈度,长截屏任意网页并编辑等等,你想到的想不到的插件几乎都能在插件市场里找到
做一个40万下载量的插件
接下来我会带领大家一边学习插件相关知识一边做一个插件,对标40万下载量的 Темная тема для ВК | Dark theme for VK ² 插件,实现切换掘金dark/light模式的插件。
manifest.json 插件的必备文件:
{
"name": "Hello, World!",
"version": "1.0",
"manifest_version": 3
}
这样我们就定义了一个名为Hello, World!的插件,同时它的版本是1.0。现在把包含manifest.json的文件夹拖进 chrome://extensions/(要先将chrome://extensions/右上角的 开发者模式 打开),
这个插件就被加载到浏览器中了
在
manifest.json同级新建一个js文件,名字任意,我取名为background1,内容为 console.log('this is background1');,并且修改manifest.json为:
{
"name": "Hello, World! demo",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background1.js"
}
}
在 chrome://extensions/点击插件上的刷新按钮,发现多了一个service worker(Inactive),点击它弹出控制台一样的窗口,点击Console,打印出了 this is background1,代表我们编写的逻辑文件已经加载到了插件里。
所有在
background1打印的内容均只能在service worker(Inactive)的Concole里看到。 插件代码的每次改动都需要刷新页面才可以加载新代码,在后续的文章中我们可以借助工具热加载解决
接下来在background1.js里添加
chrome.action.onClicked.addListener(function(){
console.log('点击了插件图标');
});
注意,此时manifest里还未做任何改动,这时刷新插件,发现有Errors
报错是非常好的学习机会,不要错过。点进去看,发现一个警告和一个error,分别是
Service worker registration failed和Uncaught TypeError: Cannot read properties of undefined (reading 'onClicked'),看error更具体一些,说没有onClicked方法,再次打印chrome.action,发现是 undefined,查看chrome.action文档发现,必须在manifest中声明才能使用此api,所以直接在manifest中添加:
{
···
"action": {}
}
清除报错,刷新插件,发现Errors消失,此时发现可以打印出来chrome.action了,并且此时点击插件图标,打印提示点击了插件图标。chrome.action这个API是专门控制插件图标的,除了响应点击事件,还可以切换图标样式,让图标展示不同的状态。
完善chrome.action.onClicked.addListener
新建icons文件夹,将图标导入项目中,将background1.js改为以下代码
let localStorage1 = 'dark'
chrome.action.onClicked.addListener(function () {
let icon = localStorage1 == 'light' ? 'dark' : 'light';
localStorage1 = icon
chrome.action.setIcon({ path: 'icons/popup_' + localStorage1 + '_32.png' });
});
点击图标,发现图标在两种状态下切换,恭喜你,完成了一个40万下载量的插件的50%的代码。
在特定的网页加载插件
接下来完善manifest.json,action和content_scripts
{
···
"action": {
"default_title": "click me",
"default_icon": {
"16": "icons/popup_dark_16.png",
"24": "icons/popup_dark_24.png",
"32": "icons/popup_dark_32.png"
}
},
"content_scripts": [{
"matches": ["https://*.juejin.cn/*"],
"js": ["content-script.js"]
}]
}
编辑content-script.js:
alert('匹配了目标页面')
然后打开掘金首页 juejin.cn,可以看到弹出消息,content-script.js,就是运行在目标网页中的逻辑
进一步编辑:
console.log('content-script运行了 2');
// alert('匹配了目标页面')
function changeBodyBackgroundColor(color = '#F00'){
document.querySelector('body').style.backgroundColor = color
console.log('设置背景颜色');
}
changeBodyBackgroundColor('#222226')
修改content-script.js为如下所示:
console.log('content-script');
document.querySelector('body').style.backgroundColor = '#22222d';
document.querySelector(".view-nav").style.backgroundColor = '#22222d';
document.querySelector("#juejin header").style.backgroundColor = '#22222d';
document.querySelector("#juejin header.list-header").style.backgroundColor = '#22222d';
function setBeforeBackgroundColor(){
var style = document.createElement("style");
document.head.appendChild(style);
sheet = style.sheet;
sheet.insertRule('.view-nav::before { background-color: #22222d }', 0);
}
function setColor(elements){
const doms = [...elements];
for (const element of doms) {
element.style.backgroundColor = '#22222d';
}
setBeforeBackgroundColor()
}
function callback(mutationList, observer) {
mutationList.forEach((mutation) => {
switch(mutation.type) {
case 'childList':
const elements = document.querySelectorAll(".entry-list-wrap .entry-list .entry, .entry-list-wrap .entry-list")
if (elements) {
setColor(elements);
}
break;
}
});
}
function observeDom(){
var targetNode = document.querySelector("#juejin .entry-list-wrap");
var observerOptions = {
childList: true, // 观察目标子节点的变化,是否有添加或者删除
// attributes: true, // 观察属性变动 这里不需要
// subtree: true // 观察后代节点,默认为 false 这里不需要
}
var observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);
}
observeDom()
可以看到页面变黑了,分几块对上述代码进行讲解:
- 可以直接拿到的元素,直接通过
querySelector找到并修改样式 - 由于掘金首页的列表内容是动态渲染的,所以无法直接取到里面的内容,这里使用
MutationObserver创建并返回一个新的观察器,它会在触发指定 DOM 事件时,调用指定的回调函数。当目标dom渲染后再触发修改样式操作。 - 对伪元素样式的修改,新建了一个样式表,在样式表里可以随意修改原class样式,当然,你也可以加载一个my-styles.css文件,在里面新增class,对原class进行覆盖:
//content-script.js
function setBeforeBackgroundColor(){
document.querySelector('.view-nav').classList.add('blackcolor')
}
//manifest.json
{
···
"content_scripts": [{
"matches": ["https://*.juejin.cn/*"],
"js": ["content-script.js"],
"css": ["my-styles.css"]
}],
}
/*my-styles.css*/
.view .blackcolor::before{ /*得益于原class只有一层,我们的class加到两层就可以覆盖原class了*/
background-color: #22222d;
}
同样可以达到修改伪元素的目的。
最终,将background1.js和content-script.js 通过chrome.runtime.onMessage.addListener 和 chrome.runtime.sendMessage连接:
// content-script.js
···
// switchTheme 切换light/dark模式
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
sendResponse('得到了结果');
const { theme } = request;
switchTheme(theme);
});
function init() {
chrome.runtime.sendMessage({}, (res) => {
const { theme } = res;
switchTheme(theme);
});
}
init();
// background1.js
···
chrome.runtime.onMessage.addListener((req,sender, sendResponse) => {
// localStorageData 是从 chrome.storage.local获取的,在插件初始化时通过 chrome.storage.local.set设置
sendResponse({theme: localStorageData})
})
结合之前 action 控制icon的逻辑,就可以通过点击icon来实现掘金首页 dark/light 切换了。由于代码量还不少,我将整体代码放在了GitHub上,供大家参考。
并且,为了让大家更方便的体验插件的内容,在误操作血亏$25注册了Google Play开发者、终于注册成功Chrome Web Store Developer但是在提交审核后填写资料出问题被拒绝、修改资料后再次提交审核后,插件终于上线了Chrome Store,现在你完全可以在Chrome Store下载一键修改掘金主题并体验。
第一版的插件并不完美,例如对字体颜色没有进行配置,后续我会进一步优化。谢谢你看到这里,欢迎点赞和评论。
参考资料:
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。