文章目录
- 一、什么是浏览器插件
- [二、快速入门:一个"Hello World"示例](#二、快速入门:一个“Hello World”示例)
-
- [2.1 项目结构](#2.1 项目结构)
- [2.2 各个文件示例和解释](#2.2 各个文件示例和解释)
- [2.3 如何使用](#2.3 如何使用)
- [三、WebExtensions API 核心组件详解 (Manifest V3)](#三、WebExtensions API 核心组件详解 (Manifest V3))
-
- [3.1 WebExtensions API 的命名空间](#3.1 WebExtensions API 的命名空间)
- [3.2 WebExtensions API 核心功能集合](#3.2 WebExtensions API 核心功能集合)
-
- [3.21 🌐 核心浏览器功能与管理](#3.21 🌐 核心浏览器功能与管理)
- [3.22🔌 扩展程序环境与运行时](#3.22🔌 扩展程序环境与运行时)
- [3.23 🖥️ 用户界面交互](#3.23 🖥️ 用户界面交互)
- [3.24 🕸️ 网络与内容交互](#3.24 🕸️ 网络与内容交互)
- [3.25 ⚠️ 核心概念(V3 重点)](#3.25 ⚠️ 核心概念(V3 重点))
- 四、跨浏览器扩展开发
-
- [4.1 异步风格](#4.1 异步风格)
- [4.2 使用 WebExtension Polyfill 来统一](#4.2 使用 WebExtension Polyfill 来统一)
- 五、发布浏览器扩展
一、什么是浏览器插件
浏览器插件(Browser Extension),也常被称为扩展程序(Extension)、插件(Plugin)、附加组件(Add-on / Addon)、加载项(Add-in)、WebExtensions(标准名)等等。
浏览器插件(Extension)本质上是一组使用 HTML、CSS 和 JavaScript 编写的网页文件,它们拥有比普通网页更强大的权限,可以访问浏览器内部的 WebExtensions API,从而实现对浏览器行为或网页内容的深度修改和控制。

🧊它和JetBrains、Visual Studio系列软件里面的插件是类似的,有如下共同特点:
- 都是依附在宿主软件里运行的可扩展功能模块
- 都通过宿主公开的扩展 API 实现功能
- 都有安装、激活、停用、卸载等生命周期
- 都被权限或沙箱机制限制可访问范围
- 都采用标准化打包方式并能在"插件商店"分发
- 更新独立,不影响宿主本体
📌 关键术语:
WebExtensions:浏览器扩展开发的统一 API 标准,由 Firefox 首创,后被 Chrome、Edge 等浏览器采纳。它定义了命名空间、方法、事件等核心结构,使扩展能够跨浏览器兼容。WebExtensions API:浏览器提供给扩展开发者的接口集合,可用于管理标签页、存储数据、监听事件等。简单来说,它就是操作浏览器的"工具箱"。Manifest V3 (MV3):Chrome、Edge 推荐使用的第三代扩展清单规范,重点在于安全性、性能和隐私保护,规定了扩展的权限、Service Worker 使用方式等。- 简单理解:WebExtensions API 是工具箱,Manifest V3 是使用工具箱时必须遵守的规则,两者共同构成现代浏览器扩展的开发基础。
前端传统三件套不必说,主要的就是WebExtensions API需要学习一下。
⏭️不多说,先来个最简单的例程体验一下吧。
二、快速入门:一个"Hello World"示例
2.1 项目结构
假设项目目录是:BrowserExtension。
最简的项目结构如下:
❗❗只有:manifest.json 必须叫这个名字,必须在根目录、必须存在。
bash
|- BrowserExtension
|- manifest.json # 插件的配置文件(身份证)
|- popup.html # 点击图标后弹出的界面
|- popup.js # 弹出窗口的逻辑脚本
当然也可以复杂一点:

2.2 各个文件示例和解释
① 插件配置:manifest.json:这是插件的配置清单,指定了插件的基本信息和权限。我们遵循最新的 Manifest V3 (MV3) 规范。
json
{
"manifest_version": 3,
"name": "简单的Hello World插件",
"version": "1.0",
"description": "一个用于演示浏览器插件基本功能的简单示例。",
"action": {
"default_title": "点击我!",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"scripting"
]
}
🔓下面是对上述json内容的具体解释,注意:json并不支持注释,下面仅仅是解释代码。
bash
{
// ============================================
// 插件基本信息配置
// ============================================
"manifest_version": 3, // 必须为3,表示使用Manifest V3规范
"name": "简单的Hello World插件", // 插件显示名称(商店中可见)
"version": "1.0", // 版本号,遵循语义化版本控制
"description": "一个用于演示浏览器插件基本功能的简单示例。", // 插件简短描述
// ============================================
// 浏览器工具栏按钮配置
// ============================================
"action": { // 定义工具栏按钮行为
"default_title": "点击我!", // 鼠标悬停时显示的提示文本
"default_popup": "popup.html" // 点击按钮时弹出的HTML页面
},
// ============================================
// 权限声明(必须明确声明所需权限)
// ============================================
"permissions": [ // 插件需要的API权限列表
"activeTab", // 访问当前激活的标签页
"scripting" // 允许向页面注入脚本
]
}
⛽JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它使用严格的文本格式来表示由
字符串键和特定类型值组成的结构化数据,支持嵌套和序列化。核心要点:
- 格式:基于键值对的结构化文本
- 键:必须是双引号包裹的字符串
- 值:仅限6种类型:字符串、数字、布尔值、null、对象、数组
- 特性:可嵌套、可序列化、跨平台通用
- (json里面不支持注释)
② 界面文件:popup.html,提供一个简单的按钮界面,并引入逻辑脚本。
html
<!DOCTYPE html>
<html>
<head>
<title>Hello Extension</title>
<meta charset="UTF-8">
<style>
/* 简单写个样式 */
body {
width: 200px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
font-family: Arial, sans-serif;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
}
</style>
</head>
<body>
<button id="alertButton">点我弹窗!</button>
<script src="popup.js"></script>
</body>
</html>
③ 逻辑脚本:popup.js,这是实现功能的关键代码。它监听按钮点击事件,并使用 WebExtensions API 向当前页面注入代码。
javascript
// popup.js
document.addEventListener('DOMContentLoaded', function() {
// 获取 HTML 中定义的按钮元素
let button = document.getElementById('alertButton');
// 给按钮添加点击事件监听器
button.addEventListener('click', function() {
// 核心功能:向当前活动标签页注入并执行一段脚本
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
// tabs[0].id 是当前活动标签页的ID
chrome.scripting.executeScript({
target: {tabId: tabs[0].id},
func: showAlert // 指定要在页面中执行的函数
});
});
});
});
/**
* 这个函数将作为"内容脚本"被注入到当前网页中执行。
* 注意:这个函数必须是自包含的,不能访问 popup.js 中的外部变量。
*/
function showAlert() {
// 在当前网页的主上下文中执行 JavaScript 的 alert 弹窗
alert('恭喜你,你的第一个浏览器插件运行成功了!');
// 也可以执行更复杂的 DOM 操作,比如:
// document.body.style.backgroundColor = 'lightblue';
}
2.3 如何使用
在 Chrome 浏览器中,地址栏输入并访问 chrome://extensions。
鼠标点击一样的:点击扩展图标,然后设置

🟢右上角:开启 "开发者模式"。
点击 "加载已解压的扩展程序",选择包含这三个文件的文件夹。

打开任意一个普通网页(非 chrome:// 开头的页面),点击工具栏上的插件图标,再点击按钮即可测试。

🟢 Chrome 内部页面(chrome:// 开头)有特殊的限制和保护机制。
- chrome:// 页面(如 chrome://settings、chrome://extensions)是 Chrome 浏览器的内部管理页面,这些页面拥有更高的权限,可以访问浏览器核心功能,为了防止恶意插件攻击浏览器本身,Chrome 禁止插件访问这些页面。
你如果使用扩展,扩展会报错:

点击错误按钮,即可看到:

点击全部清除,即可清除错误。
三、WebExtensions API 核心组件详解 (Manifest V3)
📌 关键术语:
WebExtensions:浏览器扩展开发的统一 API 标准,由 Firefox 首创,后被 Chrome、Edge 等浏览器采纳。它定义了命名空间、方法、事件等核心结构,使扩展能够跨浏览器兼容。WebExtensions API:浏览器提供给扩展开发者的接口集合,可用于管理标签页、存储数据、监听事件等。简单来说,它就是操作浏览器的"工具箱"。Manifest V3 (MV3):Chrome、Edge 推荐使用的第三代扩展清单规范,重点在于安全性、性能和隐私保护,规定了扩展的权限、Service Worker 使用方式等。- 简单理解:WebExtensions API 是工具箱,Manifest V3 是使用工具箱时必须遵守的规则,两者共同构成现代浏览器扩展的开发基础。
📗文档:https:
//developer.chrome.com/docs/extensions/get-started?hl=zh-cn
3.1 WebExtensions API 的命名空间
在编程中,命名空间(Namespace)是一种用于组织和划分代码、避免命名冲突的机制(C++和C#常见)。
在 WebExtensions API中,命名空间就是指代一系列相关联的 API 方法、属性和事件的顶级对象名称(就是全局的 chrome 或 browser 对象)。可以把它理解为浏览器扩展功能的不同 "功能模块"或"工具箱"**。
所有的 WebExtensions API 功能都挂在全局对象 chrome 或 browser下面。
例如:
javascript
// tabs 是一个命名空间
chrome.tabs.query({active: true}, function(tabs) {
console.log(tabs[0].url);
});
- chrome 就是顶级对象,它是整个扩展 API 的入口。
- tabs 是 chrome 下的命名空间,里面有一系列方法(query、create、update 等)和事件(onCreated、onUpdated 等)。
- 命名空间就是 chrome 对象下的第一个子属性。
- 调用 API 时,您需要先指定命名空间,再调用具体的方法
格式:
bash
调用格式: chrome.[命名空间].[方法/属性/事件]
命名空间的作用:
| 作用 | 解释 | 示例 |
|---|---|---|
| 功能隔离 | 将不相关的功能划分到不同的模块,使得 API 结构清晰、易于查找和理解。 | tabs 命名空间只处理标签页,bookmarks 命名空间只处理书签,它们的功能不会混淆。 |
| 权限控制 | 扩展程序只有在 manifest.json 中声明了相应的权限后,才能访问对应的命名空间。 |
声明 "permissions": ["tabs"] 才能使用 chrome.tabs 的大部分功能;未声明就无法使用。 |
| 避免冲突 | 确保不同的功能模块即使有相同名称的方法(例如:create),也不会互相干扰。 |
chrome.tabs.create 用于创建标签页;chrome.windows.create 用于创建窗口。名称相同,但功能和上下文不同。 |

3.2 WebExtensions API 核心功能集合
3.21 🌐 核心浏览器功能与管理
这部分 API 允许扩展程序直接操作浏览器环境,是构建大部分实用工具的基础。
| 命名空间(英文) | Manifest V3 变化 | 主要修正/优化 |
|---|---|---|
tabs |
稳定 | 修正:管理单个标签页的属性(URL、标题、加载状态等)和行为。 |
windows |
稳定 | 修正:管理整个浏览器窗口(打开、关闭、最大化、获取焦点等)。 |
sessions |
稳定 | 优化:在 Chrome 中用于管理最近关闭的标签页和窗口。 |
bookmarks |
稳定 | 优化:提供完整的书签 CRUD (创建、读取、更新、删除) 操作。 |
history |
稳定 | 优化:访问和管理用户的浏览器访问历史记录。 |
downloads |
稳定 | 优化:监听、启动、暂停和取消文件下载。 |
3.22🔌 扩展程序环境与运行时
这部分 API 关注扩展程序自身的生命周期、配置和内部通信。
| 命名空间(英文) | Manifest V3 变化 | 主要修正/优化 |
|---|---|---|
runtime |
核心 | 修正:扩展程序的生命周期 、安装事件 、版本信息 、长连接和一次性消息传递。 |
storage |
核心 | 修正:提供 local (本地)、sync (同步) 和 managed (企业管理) 三种存储区。必须用于持久化数据,因为 Service Worker 不保证持续运行。 |
i18n |
稳定 | 优化:用于国际化和多语言支持。 |
identity |
稳定 | 优化:实现 Chrome 或 Firefox 用户的OAuth2 授权流程。 |
3.23 🖥️ 用户界面交互
这些 API 用于在浏览器中创建可见的、用户可交互的界面元素。
| 命名空间(英文) | Manifest V3 变化 | 主要修正/优化 |
|---|---|---|
action |
更名/核心 | 重要修正 :在 Manifest V3 中,browserAction 和 pageAction 合并为 action。负责工具栏按钮、弹出窗口和徽章(Badge Text)。 |
contextMenus |
稳定 | 修正:在右键上下文菜单中添加自定义项目。 |
notifications |
稳定 | 修正:创建和管理桌面通知。 |
omnibox |
稳定 | 修正:注册关键字,在浏览器地址栏(智能框)提供自定义建议。 |
3.24 🕸️ 网络与内容交互
这是扩展程序中最强大和最敏感的部分,需要更严格的权限管理。
| 命名空间(英文) | Manifest V3 变化 | 主要修正/优化 |
|---|---|---|
webRequest |
重要变化 | 修正 :在 Manifest V3 中,webRequest 仅能用于观察和分析 网络请求。不允许在 Service Worker 中进行同步阻断操作。 |
declarativeNetRequest |
V3 核心 | 重要修正 :在 Manifest V3 中,用于阻断、重定向和修改请求 ,是 webRequest 阻断功能的替代品。它使用静态规则集,效率更高,但功能更受限。 |
cookies |
稳定 | 优化:获取、设置和监听 HTTP Cookies 的变化。 |
contentScripts |
稳定 | 优化:是机制而非 API 命名空间 。它允许脚本在网页中运行,并使用 runtime.sendMessage 和 tabs.sendMessage 与后台通信。 |
3.25 ⚠️ 核心概念(V3 重点)
| 概念 | 修正/优化 |
|---|---|
| Service Worker | 重要修正 :取代了 Manifest V2 中的 background.html(后台页面)。Service Worker 是基于事件驱动 的,会在不活跃一段时间后被关闭 ,因此数据必须持久化到 storage,且不支持同步操作。 |
| 主机权限 (Host Permissions) | 优化:例如 <all_urls>、*://*.google.com/*,用于授予扩展程序在特定 URL 上执行内容脚本或调用 API 的权限。 |
| 权限(Permissions) | 优化:用于启用特定的 API 命名空间,例如 "tabs"、"history"、"webRequest" 等。 |
四、跨浏览器扩展开发
主流浏览器主要有 Chrome、Edge 和 Firefox。它们都基于 WebExtensions 标准开发扩展,因此绝大多数 API 兼容性良好,跨浏览器开发相对简单。
主要差别在于顶级对象和异步风格不同(实际情况更复杂,比如用户浏览器版本不同,浏览器对标准的支持情况):
| 浏览器 | 顶级对象 | 异步风格 | 风格备注 |
|---|---|---|---|
| Chrome | chrome |
回调(callback) | 原生 Chromium 风格(正转向 Promise) |
| Edge (Chromium) | chrome / browser |
回调 / Promise | browser 为兼容 Firefox 提供 Promise 封装 |
| Firefox | browser / chrome |
Promise / 回调 | 官方推荐 browser 和 Promise |
4.1 异步风格
同步和异步指的是代码执行的顺序和阻塞机制。
- 同步风格(
Synchronous Style,阻塞式): 代码按照编写的顺序逐行执行。当执行到某个操作时,程序会停下来等待该操作彻底完成并返回结果后,才能继续执行下一行代码。在浏览器环境中,长时间的同步操作会导致浏览器界面卡死(冻结),用户体验非常差。 - 异步风格(
Asynchronous Style,非阻塞式): 代码按照编写的顺序发起任务,但不会停下来等待。程序会立即继续执行下一行代码。当耗时的任务完成后,会通过某种机制(如回调函数callback、Promise)来通知程序并处理结果。
| 特性 | 同步风格 (Synchronous) | 异步风格 (Asynchronous) |
|---|---|---|
| 执行模式 | 顺序执行,逐行等待 | 非阻塞执行,任务发起后立即返回 |
| 程序状态 | 阻塞(Block) | 非阻塞(Non-Block) |
| 等待机制 | 必须等待当前操作完成才能继续 | 操作在后台进行,通过事件、回调或 Promise 等通知结果 |
| 应用场景 | 适用于 CPU 密集型任务,或者对时间要求不高的简单操作。 | 适用于 I/O 密集型任务(网络请求、文件读写、数据库操作、浏览器 API 调用等)。 |
| 用户体验 | 在耗时操作时,程序/界面会卡死 | 程序/界面保持响应,用户体验好 |
| 代码实现 | 直接的函数调用 (例如:const result = add(1, 2);) |
回调函数 (Callback) 、Promise 、Async/Await 等 |
| 浏览器扩展 API 例子 | - | chrome.tabs.query(...) (回调或 Promise) |
| 主要优点 | 简单、易于理解和调试 | 充分利用资源,提高程序效率和响应性 |
浏览器扩展 API(如 chrome.tabs.query() 或 browser.storage.local.get())涉及大量**输入/输出(I/O)**操作,这些操作都可能需要时间,所以它们必须设计成异步的,以防止浏览器卡死。
异步风格主要有两种代码体现方式:
🟢A. 回调函数风格(Callback Style)- 传统 Chrome 风格
这是 Chrome 扩展 API 早期和传统使用的风格。在调用异步函数时,需要提供一个函数作为参数 (即回调函数)。当异步任务完成后,系统会调用这个回调函数,并将结果作为参数传递给它。
bash
// 回调风格示例
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
// 异步操作(查询标签页)完成后,这段代码才会被执行
console.log("当前激活的标签页 ID 是:", tabs[0].id);
// 这里如果发生错误,错误处理会很复杂(回调地狱)
});
console.log("这行代码会先于上面的结果被打印");
🟢Promise 风格(Promise Style)- 现代 Firefox/Edge 推荐风格
Promise 是一种更现代的异步处理方式,它代表了一个未来可能完成 的异步操作的结果。它能更好地处理异步操作的成功(then)和失败(catch) ,并能通过链式调用(Promise Chain)解决回调函数嵌套过深的问题(回调地狱)。
chrome也正在转向这种风格。
bash
// Promise 风格示例
browser.tabs.query({active: true, currentWindow: true})
.then(tabs => {
// 异步操作(查询标签页)成功后,这段代码才会被执行
console.log("当前激活的标签页 ID 是:", tabs[0].id);
})
.catch(error => {
// 捕获异步操作中的错误
console.error("查询标签页时出错:", error);
});
console.log("这行代码会先于上面的结果被打印");
4.2 使用 WebExtension Polyfill 来统一
WebExtension Polyfill 是一个小的 JavaScript 库,它会自动检测当前运行的环境(Chrome、Edge 还是 Firefox),然后:
- 如果发现浏览器使用 browser 命名空间(Firefox 的标准),它会将所有 browser.* 方法映射到 chrome.* 方法。
- 如果发现浏览器使用 chrome 命名空间(Chrome/Edge 的标准),它会反过来创建缺失的 browser 对象,并将其所有方法映射到 chrome.*。
文件地址:https://github.com/mozilla/webextension-polyfill
本文写的示例很简单,只需要稍改一下,不使用Polyfill ,就能兼容三大浏览器:
json
{
"manifest_version": 3,
"name": "简单的Hello World插件",
"version": "1.0",
"description": "一个用于演示浏览器插件基本功能的简单示例。",
"action": {
"default_title": "点击我!",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"scripting"
],
"browser_specific_settings": {
"gecko": {
"id": "helloworld@example.com",
"strict_min_version": "109.0"
}
}
}
Gecko 是 Firefox 浏览器的核心引擎名称,在 Manifest V3 标准下,Chrome 是在安装时自动生成 ID 的,但 Firefox 强制要求开发者在 manifest.json 里显式声明这个 ID。如果不写,Firefox 在加载插件时会直接报错,认为这是一个无效的插件。
bash
"browser_specific_settings": { // 1. 浏览器专用设置
"gecko": { // 2. 指定针对 Gecko 内核(即 Firefox)
"id": "helloworld@example.com", // 3. 插件的唯一 ID(必须)
"strict_min_version": "109.0" // 4. 最低支持的 Firefox 版本
}
}
edge和chrome是类似的,打开开发人员选项即可加载。
chrome是在扩展界面,点击设置:调试附加组件,选择:manifest.json即可。
五、发布浏览器扩展
-
源码分享 / 本地安装
- 直接分享扩展目录(解压后的文件夹)或打包成
.crx文件都可以本地安装。 - 注意:Chrome 和 Edge 对直接拖入目录的本地安装有安全限制,本地安装一般在开发者模式下进行。
- 安装
.crx后,可以删除.crx文件,因为浏览器已经加载了扩展;本地目录方式安装,则源文件不可删除。

- 直接分享扩展目录(解压后的文件夹)或打包成
-
发布到浏览器扩展商店
- 需要注册开发者账号(Chrome Web Store 是一次性 5 美元费用,火狐免费),提交扩展并通过审核才能上架。
- 扩展需符合规范:icon、描述、权限声明、文档等。
- 上架后用户可直接下载安装,无需手动文件操作。
注册地址:https://chrome.google.com/webstore/devconsole/register