从 0 到 1:开启 Chrome 插件开发的奇妙之旅

1. 引言

谈到 Chrome 插件,相信大家都不陌生,我们可以使用 Chrome 插件实现广告拦截、数据抓取、标签管理等功能,这些能力让我们有更好的浏览体验和更高效的办公效率。

Chrome 应用商店中已有各式各样的插件,你当然可以在这里下载你所需要的插件,不过有时你还是需要打造一个更符合自己或团队的插件,以此提升效能,所以学习 Chrome 插件开发是一项极具价值的技能。

Chrome 插件的开发门槛相对较低,只需掌握基础的 HTML、CSS 和 JavaScript 知识即可入门,同时又能快速实现实用的功能。

本文将带你从零开始,了解 Chrome 插件的基本架构和核心 API,并通过几个简单的实例演示,让你体验 Chrome 插件开发流程。

2. 基础概念

2.1 插件构成

Chrome 插件通常由以下几部分组成:

  • manifest.json:核心配置文件,指定插件的名称、版本、图标等基础信息,同时根据插件功能在此声明权限,确定要在后台和网页上运行哪些文件。
json 复制代码
{
  "manifest_version": 3,  // 3为最新规范
  "name": "我的插件",
  "version": "1.0",
  "description": "插件描述",
  "icons": {
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "action": {  // 浏览器工具栏按钮配置,可选
    "default_popup": "popup.html",
    "default_icon": "icon.png"
  },
  "background": {  // 后台服务,可选
    "service_worker": "background.js"
  },
  "content_scripts": [{  // 注入网页的脚本,可选
    "matches": ["<all_urls>"],
    "js": ["content.js"]
  }],
  "permissions": ["storage", "tabs"],  // 需申请的权限,可选
}
  • Content Scripts:内容脚本文件,可通过 DOM 操作网页内容。
  • Service Worker:用于执行后台任务,在扩展程序的整个生命周期中持续运行。
  • Toolbar action(Popup):点击扩展程序图标时弹出的页面。

2.2 核心 API

Chrome 插件开发的核心在于利用浏览器提供的 Extension API,这些 API 让插件能够与浏览器交互,操作标签页、存储数据、拦截网络请求等。

chrome.tabs - 标签页管理

用途:操作浏览器标签页,如创建、切换、关闭或获取当前活动标签页。

常用方法:

  • chrome.tabs.create() - 打开新标签页
  • chrome.tabs.query() - 查询符合条件的标签页
  • chrome.tabs.update() - 修改标签页(如跳转 URL)
  • chrome.tabs.remove() - 关闭标签页
  • chrome.tabs.sendMessage() - 向指定标签页中的内容脚本发送一条消

示例:

javascript 复制代码
// 获取当前活动标签页
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
  console.log("当前标签页:", tabs[0].url);
});

// 在新标签页打开网址
chrome.tabs.create({ url: "https://example.com" });

chrome.action - 管理浏览器工具栏按钮

用途:允许开发者控制插件图标的外观、交互行为以及弹出窗口(Popup)。

常用方法:

  • chrome.action.setIcon() - 动态修改图标
  • chrome.action.setTitle() - 修改标题
  • chrome.action.setPopup() - 动态修改 Popup 页面
  • chrome.action.setBadgeText() - 设置徽章文字
  • chrome.action.enable() - 启用工具栏按钮
  • chrome.action.disable() - 禁用工具栏按钮
  • chrome.action.onClicked.addListener - 当用户点击工具栏按钮时触发(未设置 Popup 时有效)

示例:

js 复制代码
// 当插件激活时切换图标
chrome.action.setIcon({
  path: isActive ? "icons/active.png" : "icons/inactive.png"
});

// 根据权限状态切换不同弹窗
chrome.action.setPopup({
  popup: hasPermission ? "popup.html" : "permission.html"
});

// 设置红色徽章显示数字
chrome.action.setBadgeText({ text: "5" });

// 仅在特定网站启用
chrome.tabs.onActivated.addListener(({ tabId }) => {
  chrome.tabs.get(tabId, (tab) => {
    const isGmail = tab.url.includes("mail.google.com");
    isGmail ? chrome.action.enable(tabId) : chrome.action.disable(tabId);
  });
});

chrome.action.onClicked.addListener((tab) => {
  console.log("点击了插件图标,当前标签页:", tab.url);
  // 可以在这里执行逻辑,如打开新页面
  chrome.tabs.create({ url: "https://example.com" });
});

chrome.storage - 数据存储

用途:存储插件数据,当用户清除浏览数据时,扩展程序存储空间不会被清除。

两种存储方式:

  • chrome.storage.local - 本地存储(仅当前设备)
  • chrome.storage.sync - 同步存储(跨设备,需用户登录 Chrome)

示例:

js 复制代码
// 存储数据
chrome.storage.local.set({ key: "value" }, () => {
  console.log("数据已保存");
});

// 读取数据
chrome.storage.local.get(["key"], (result) => {
  console.log("读取到的数据:", result.key);
});

chrome.runtime - 插件生命周期与通信

用途:管理插件运行环境,支持后台脚本与内容脚本通信。

常用方法:

  • chrome.runtime.sendMessage() - 发送消息(用于不同脚本间通信)
  • chrome.runtime.onMessage.addListener() - 监听消息
  • chrome.runtime.getURL() - 获取插件内资源的绝对路径
  • chrome.runtime.onInstalled() - 安装或更新插件触发

示例:

js 复制代码
// 内容脚本(content.js)发送消息
chrome.runtime.sendMessage({ action: "greet", data: "Hello from content script!" });

// 后台脚本(background.js)接收消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === "greet") {
    console.log("收到消息:", request.data);
    sendResponse({ reply: "Message received!" });
  }
});

// background.js (Service Worker)
chrome.runtime.onInstalled.addListener((details) => {
  if (details.reason === "install") {
    console.log("首次安装");
    // 初始化默认数据
    chrome.storage.local.set({ config: defaultSettings });
  } 
  else if (details.reason === "update") {
    console.log(`从版本 ${details.previousVersion} 更新`);
    // 执行数据迁移
  }
});

chrome.webRequest - 网络请求拦截与修改

用途:监控或修改 HTTP 请求(需在 manifest.json 声明权限)。

适用场景:

  • 广告拦截
  • 请求重定向
  • 修改请求头

示例(拦截请求):

js 复制代码
// 在 manifest.json 中添加权限:
// "permissions": ["webRequest", "webRequestBlocking", "<all_urls>"]

chrome.webRequest.onBeforeRequest.addListener(
  function(details) {
    return {cancel: details.url.indexOf("://www.evil.com/") != -1};
  },
  { urls: ["<all_urls>"] },
  ["blocking"]
);

chrome.contextMenus - 右键菜单定制

用途:在浏览器右键菜单中添加自定义选项。

示例:

js 复制代码
// 在 manifest.json 中添加权限:
// "permissions": ["contextMenus"]

chrome.contextMenus.create({
  id: "search-google",
  title: "Search Google for '%s'", // %s 会替换成选中的文本
  contexts: ["selection"], // 仅在选择文本时显示
});

// 监听菜单点击事件
chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (info.menuItemId === "search-google") {
    const query = encodeURIComponent(info.selectionText);
    chrome.tabs.create({ url: `https://www.google.com/search?q=${query}` });
  }
});

chrome.notifications - 桌面通知

用途:向用户发送系统级通知(需权限)。

示例:

js 复制代码
// 在 manifest.json 中添加权限:
// "permissions": ["notifications"]
chrome.notifications.create("reminder", {
  type: "basic",
  iconUrl: "icon.png",
  title: "提醒",
  message: "您有一条新消息!",
});

3. 插件开发

接下来让我们通过实例演示来看看插件如何开发。

3.1 Hello World

按学习编程惯例,我们先实现一个 Hello World 功能,让用户点击插件图标时,弹出一个 Hello World 界面。

要想实现此功能,插件只需创建 manifest.json 和 popup,先如下创建对应的插件项目结构:

bash 复制代码
HelloWolrd
├── images
│   ├── icon-16.png
│   ├── icon-32.png
│   ├── icon-48.png
│   └── icon-128.png
├── popup
│   ├── popup.css
│   └── popup.html
└── manifest.json

图片可以直接去 iconfont 上下载即可,我们先来看下 manifest.json。

json 复制代码
{
  "manifest_version": 3,
  "name": "Hello Extensions",
  "description": "Base Level Extension",
  "version": "1.0",
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "action": {
    "default_popup": "popup/popup.html"
  },
}

manifest.json 中有 5 个基本配置项(插件规范版本、插件名称、插件描述、插件版本、插件图标)和工具栏按钮配置(action)。

在工具栏按钮配置中使用 default_popup 指定了点击按钮后弹窗要展示的内容。弹窗的内容就是 html、css、javascript 组成,在本示例中我们简单实现下。

popup.html 内容如下:

html 复制代码
<html>
  <head>
    <link rel="stylesheet" href="./popup.css">
  </head>
  <body>
    <h1>Hello World</h1>
    <p class="blue">blue text</p>
  </body>
</html>

popup.css 内容如下:

css 复制代码
body {
  width: 150px;
}

.blue {
  color: #1677ff;
}

至此我们就完成了一个 Hello World 的插件编写,接着我们要在浏览器上加载此插件,并查看效果。

可如下加载本地插件:

  1. 在浏览器新标签页中输入 chrome://extensions,或者通过工具栏打开。
  2. 点击开发者模式旁边的切换开关,即可启用开发者模式。
  3. 点击加载已解压缩的文件按钮,然后选择扩展程序目录(本示例中即 HelloWolrd 文件夹)。

安装完插件,我们就可以在工具栏点击插件,查看效果。

3.2 运行内容脚本

内容脚本可以静态声明、动态声明或以编程方式注入,本示例将以静态声明方式注入,其他方式可以查看内容脚本文档

首先创建项目结构:

bash 复制代码
ContentScript
├── images
│   ├── icon-16.png
│   ├── icon-32.png
│   ├── icon-64.png
│   └── icon-128.png
├── content.js
└── manifest.json

manifest.json 如下:

json 复制代码
{
  "name": "Hello Content Script",
  "description": "Base Level Extension",
  "version": "1.0",
  "manifest_version": 3,
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "content_scripts": [
    {
      "js": ["content.js"],
      "matches": ["<all_urls>"]
    }
  ]
}

内容脚本的注入通过 content_scripts 进行,在这个字段中,我们指定了要执行的脚本和哪些网页会执行该脚本,<all_urls> 代表匹配所有网址。

接下来看 content.js 内容:

js 复制代码
const div = document.createElement('div')
div.innerText = '插件内容'
document.body.prepend(div)

该脚本内容会在 body 中插入一个文本内容,加载插件后刷新下页面即可看到页面多了个"插件内容"的文字。

3.3 使用 Service Worker 处理事件

我们可以用 Service Worker 来监听浏览器标签更新、监听插件安装或更新、定时通知提醒、广告拦截、与弹出窗口或内容脚本通信等等。

本示例中我们使用 Service Worker 往内容脚本发消息,消息内容为当前 tab 的标题。

项目结构如下:

bash 复制代码
ServiceWorker
├── images
│   ├── icon-16.png
│   ├── icon-32.png
│   ├── icon-64.png
│   └── icon-128.png
├── content.js
├── manifest.json
└── service-worker.js

相比于上个示例,manifest.json 中多了两个字段:

json 复制代码
{
  "name": "Hello ServiceWorker",
  "description": "Base Level Extension",
  "version": "1.0",
  "manifest_version": 3,
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "permissions": ["tabs"],
  "content_scripts": [
    {
      "js": ["content.js"],
      "matches": ["<all_urls>"]
    }
  ],
  "background": {
    "service_worker": "service-worker.js"
  }
}

使用 background.service_worker 字段指定后台运行的脚本。因为我们要读取标签页的标题,所以我们需要加个权限说明 "permissions": ["tabs"]

接着 service-worker 的代码如下:

js 复制代码
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete') {
    chrome.tabs.sendMessage(tab.id, {
      data: tab.title,
    })
  }
});

chrome.tabs.onUpdated 的作用是监听标签页加载完成或更新,入参的回调函数中,我们控制当页面加载完成时,后台脚本会往 tabs 发送一个消息,消息内容为标签页面标题。

js 复制代码
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  const div = document.createElement('div')
  div.innerText = request.data
  document.body.prepend(div)
})

内容脚本使用 chrome.runtime.onMessage 来监听消息,收到消息后输出到页面,效果如下:

3.4 替换页面

你可能有使用过一些插件来替换浏览器的默认标签页,本示例将带你实现这个功能。

先看下项目结构:

bash 复制代码
NewTab
├── images
│   ├── icon-16.png
│   ├── icon-32.png
│   ├── icon-64.png
│   └── icon-128.png
├── myPage.html
└── manifest.json

项目结构中主要是 manifest.json 和 myPage.html,我们需要在 manifest.json 中定义使用 myPage.html 替换默认标签页。

js 复制代码
{
  "name": "Hello NewTab",
  "description": "Base Level Extension",
  "version": "1.0",
  "manifest_version": 3,
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "chrome_url_overrides" : {
    "newtab": "myPage.html"
  }
}

可以看到 manifest.json 中定义了一个 chrome_url_overrides 字段,里面指定了 newtab 要加载 myPage.html

除了覆盖默认标签页,你还可以覆盖历史记录和书签页面,"history": "myPage.html""bookmarks": "myPage.html"

接下来就是 myPage.html 内容:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <p>我的标签页</p>
</body>
</html>

加载插件后,打开一个新的标签页,效果如下:

4. 插件调试

插件工具栏弹窗内容的可以通过右键插件图标,选择"审查弹出内容"即可打开 Chrome 调试工具。

4.2 Service Worker 调试

Service Worker 的调试在插件管理界面,如果你的插件有后台脚本,可以点击插件的 "检查视图 Service Worker" 打开 Chrome 调试工具。

4.3 content-script 调试

内容脚本的调试需要在当前标签页打开 Chrome 开发者工具,在"源代码/来源"页签的左侧中找到"内容脚本",选择你插件的内容脚本即可开始调试。

5. 总结

至此我们已经完成了 Chrome 插件开发的入门,更多内容可查阅官方文档

如果你有好的想法,可以尝试自己开发一款 Chrome 插件,在实现自己想法的同时,或许可以通过插件获取收益。

相关推荐
星空寻流年4 小时前
css3伸缩盒模型第二章(侧轴相关)
javascript·css·css3
GalenWu5 小时前
对象转换为 JSON 字符串(或反向解析)
前端·javascript·微信小程序·json
zwjapple5 小时前
“ES7+ React/Redux/React-Native snippets“常用快捷前缀
javascript·react native·react.js
数据潜水员5 小时前
插槽、生命周期
前端·javascript·vue.js
2501_907136826 小时前
CSS 学习与工程化实践指南
css
优雅永不过时·6 小时前
实现一个漂亮的Three.js 扫光地面 圆形贴图扫光
前端·javascript·智慧城市·three.js·贴图·shader
春天姐姐8 小时前
vue知识点总结 依赖注入 动态组件 异步加载
前端·javascript·vue.js
Pop–9 小时前
Vue3 el-tree:全选时只返回父节点,半选只返回勾选中的节点(省-市区-县-镇-乡-村-街道)
开发语言·javascript·vue.js
滿9 小时前
Vue3 + Element Plus 动态表单实现
javascript·vue.js·elementui
阿金要当大魔王~~9 小时前
面试问题(连载。。。。)
前端·javascript·vue.js