写一个去广告插件

152 阅读3分钟

web技术除了开发网站,还可以开发Chrome插件,相比于网页,插件具有以下优点:

  1. 部署发布方便,不需要购买服务器。

  2. 除了可以使用web开发的各种UI技术,还能使用Chrome API。

  3. 能够运行在任何网站,能够定制浏览器。

总的来说,插件开发只有掌握基本的web开发技能即可,Chrome API在需要使用的场合查询即可,在使用中积累。

manifest声明文件

插件最重要的文件是manifest,里面定义了基本元信息(插件名,描述等),插件特定信息(permissions,content scripts, background, popup等)。

脚手架

定义完manifest文件后,我们可以根据自己需求写对应脚本和UI,但是自己一个个写太麻烦,所以最方便是找一个脚手架。这里选用umi-chrome-extensions-template。这款脚手架内置typescript,react18的支持,各个脚本和UI文件都有模板代码,目录清晰,我们只需要在对应的目录文件里修改即可。

比如我们需要有popup界面,那就修改pages/popup里面的代码,直接用react写界面。如果需要修改content script就修改contentScripts目录里的文件,如果要修改元信息,就去根目录的config目录下修改配置代码。

开发一个去广告插件

目的:我们希望实现一个插件能够去掉product hunt网站上带有promoted的条目。

  1. 思路分析

为了去掉特定网站的某些内容,我们只有使用content script在该网站下注入脚本筛选出满足条件的dom元素,隐藏它们即可。

  1. 创建项目

明确需求后,我们首先下载上一步提到的脚手架项目,安装好依赖。然后可以运行下build命令,得到插件产物,在chrome浏览器开发者模式下,加载产物就可以看到脚手架提供的插件模版效果

  1. 修改manifest声明

在脚手架项目里,我们看不到manifest文件,因为它是最终编译生成的,如果进行了上一步应该可以在编译产物的dist目录里看到生成的manifest文件。如果我们需要修改manifest,需要到config目录下的配置文件里修改。这里我们需要修改插件名,插件描述,图标(如果你有),content scripts的生效网站的正则表达式(这里写product hunt的域名)。修改结果如下:

export default defineConfig({
  plugins: [require.resolve('umi-plugin-extensions')],
  extensions: {
    name: 'Adblock',
    description: '基于 Umi 的 Chrome 插件开发脚手架',
    optionsUI: {
      page: '@/pages/options',
      openInTab: true,
    },
    background: { service_worker: '@/background/index' },
    popupUI: '@/pages/popup',
    contentScripts: [
      { matches: ['https://www.producthunt.com/*'], entries: ['@/contentScripts/all'] },
    ],
    icons: {
      16: 'logo/logo@16.png',
      32: 'logo/logo@32.png',
      48: 'logo/logo@48.png',
      128: 'logo/logo@128.png',
    },
  },
});

其他内容暂时用不到,保留原样。

  1. 修改content script

function removeAds() {
  const ads = document.querySelectorAll('div[data-test^="ad-slot-"]');
  ads.forEach(i => i.setAttribute('style', 'display: none !important;'))
}

// Ensures ads will be removed as the user scrolls
setInterval(function () {
  removeAds();
}, 100)

content script里的代码如上,我们定义一个函数,然后定时调用该函数,因为我们可能会滚动,定时调用可以在滚动后也去除对应dom。这个函数很简单通过querySelector选择匹配正则表达式的dom,然后设为隐藏。我们来看下选择器div[data-test^="ad-slot-"],表示的是所有data-test属性都是以ad-slot开头的dom元素。这里的^是正则的匹配符号。

  1. 打包使用

改完后,运行build命令,重新加载插件,就可以到product hunt上看看效果了。