admin 管理员组文章数量: 1184232
1. 前言
这篇文章将通过一个简单的改变网页背景颜色的扩展程序,带你了解 Chrome 扩展程序的开发流程以及核心概念。
2. 前提条件
-
了解前端开发,熟悉使用 html,css,javascript。
PS: 我开发的一款AI助手插件已发布至 chrome 应用商店,你可以通过搜索‘顾得助手’安装。或者通过github下载体验最新功能:https://github/herogus/good_ai_chrome_extension 。
3. 核心概念
3.1 整体概览
简而言之,chrome 扩展程序的核心内容主要是以下几个文件:manifest.json、popup.html、content.js、background.js。首先我们先了解这几个文件在浏览器中的位置。
popup.html 和 内容脚本(content.js),内容脚本的日志输出在网页控制台。
background.js
3.2 manifest.json
manifest.json 是 扩展的核心配置文件,用于声明扩展的基本信息、权限、功能模块、脚本资源等。浏览器通过它来识别、加载和运行你的扩展。
注:此文件是必须文件,否则导入的扩展程序到chrome 时会报 “无法加载清单文件”。
3.2.1 主要作用:
| 作用 | 说明 |
|---|---|
| 描述扩展 | 指定扩展名称、版本、描述等基础信息 |
| 定义入口 | 指定背景脚本(background)、内容脚本(content)、popup 页面、options 页面等 |
| 请求权限 | 声明扩展需要访问的权限(如 storage、tabs、activeTab、scripting) |
| 指定资源 | 列出图标、页面、脚本、样式等资源文件 |
| 控制行为 | 控制扩展的运行时行为,比如注入哪些页面、加载时机、默认语言等 |
| 声明兼容性 | 指定 manifest版本(如 2 或 3),必须是 V3,Google 已停止对 V2 的支持。 |
3.2.2 常见配置与说明
下面是以 Manifest V3 版本为例,一个功能完整的扩展程序配置清单:
{
"manifest_version": 3,
"name": "我的扩展",
"version": "1.0.0",
"description": "这是一个功能完整的 Chrome 扩展",
"icons": {
"16": "icons/icon-16.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
},
"permissions": [
"storage",
"tabs",
"scripting"
],
"host_permissions": [
"*://*/*"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon-16.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
}
},
"options_ui": {
"page": "options.html",
"open_in_tab": true
},
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_idle"
}],
"web_accessible_resources": [{
"resources": [
"imgs/*",
"styles/*",
"scripts/*"
],
"matches": ["*://*/*"]
}]
}
3.2.2.1 字段说明
| 字段 | 二级字段 | 字段值 | 字段说明 |
|---|---|---|---|
| manifest_version | - | 3 | 清单版本号。必须是 3(V3 是当前标准)。 |
| name | - | "我的扩展" | 扩展程序的名称,显示在扩展管理页、Chrome 商店等。 |
| version | - | "1.0.0" | 扩展程序的版本号,例如 "1.0.0",用于版本管理和 Chrome 应用商店的更新检测。 |
| description | - | "这是一个功能完整的 Chrome 扩展" | 扩展程序的简要描述,说明功能或目的,显示在扩展管理页面和应用商店。 |
| icons | - | - | icons 用来指定不同大小的图标及路径,用于扩展列表、通知、工具栏等。推荐PNG格式。 |
| 16 | "icons/icon-16.png" | 定义16x16像素图标,用于扩展栏或标签页显示。 | |
| 48 | "icons/icon-48.png" | 定义48x48像素图标,用于Chrome扩展管理页面显示(chrome://extensions/)。 | |
| 128 | "icons/icon-128.png" | 定义128x128像素图标,用于Chrome网上应用店的显示。 | |
| permissions | - | ["storage", "tabs", "scripting"] | 定义基础权限。 storage表示允许使用chrome.storage API存储和检索数据。 tabs表示允许访问和操作浏览器标签页,比如:获取标签页URL、标题,或创建/关闭标签页。 scripting表示允许脚本注入。 |
| host_permissions | - | ["*://*/*"] | 主机权限,指定可访问的网页 URL,例如:"*://*/*"、"https://*/*"。 "*://*/*" 表示所有网页。 |
| background | - | - | 后台脚本设置(V3 使用 service_worker) |
| service_worker | "background.js" | 指定后台脚本文件。 | |
| action | - | - | 定义扩展图标的行为(工具栏按钮) |
| default_popup | "popup.html" | 指定点击扩展图标时弹出的页面路径,提供交互式UI,如设置面板或功能入口。 | |
| default_icon | { "16": "icons/icon-16.png", "48": "icons/icon-48.png", "128": "icons/icon-128.png" } | 定义工具栏中显示的图标及路径,优先于icons字段,用于扩展栏显示。 | |
| options_ui | - | - | 用于配置扩展程序设置界面。 |
| page | "options.html" | 设置页面的 HTML 文件路径。 | |
| open_in_tab | true | 控制选项页面显示方式。 true表示在新标签页打开,推荐; false表示嵌入式显示。 | |
| content_scripts | - | - | 网页注入脚本设置(运行在页面上下文中)。 |
| matches | ["*://*/*"] | 指定内容脚本运行的网页URL模式。 如:"*://*/*"表示所有页面生效。 如何配置见拓展2。 | |
| js | ["content.js"] | 注入的 JS 文件列表。 | |
| run_at | "document_idle" | 指定脚本注入时机。 document_idle表示页面DOM加载完成后注入,适合大多数内容脚本场景。 document_start 表示在 DOM 创建之前注入,适合拦截页面脚本或注入变量。 document_end表示在 DOM 加载完成后,可操作 DOM 元素但不保证全部加载。 | |
| web_accessible_resources | - | - | 允许网页访问扩展的资源(如图片、JS、样式)。 |
| resources | ["imgs/*", "styles/*", "scripts/*"] | 允许网页或内容脚本加载的资源路径。 | |
| matches | ["*://*/*"] | 可访问这些资源的网页 URL 范围。 "*://*/*"表示所有网页可加载这些资源。 |
3.2.2.2 拓展1permissions 的常用值列表
| 权限名 | 类型 | 说明 |
|---|---|---|
| storage | 基础 | 使用 chrome.storage存储数据 |
| tabs | 基础 | 访问、操作浏览器标签页 |
| activeTab | 基础 | 临时访问当前激活的标签页,常用于注入脚本 |
| scripting | 基础 | 使用 chrome.scripting API 注入脚本和样式 |
| contextMenus | 界面 | 创建自定义右键菜单项 |
| notifications | 界面 | 显示系统通知 |
| downloads | 网络 | 触发文件下载、监听下载进度 |
| clipboardRead | 输入输出 | 读取剪贴板内容(仅 HTTPS 有效) |
| clipboardWrite | 输入输出 | 写入剪贴板内容 |
| history | 浏览器 | 读取用户浏览器历史记录 |
| webRequest | 网络 | 拦截和查看网络请求(需 host 权限) |
| webRequestBlocking | 网络 | 同步阻塞请求(用于拦截器、防广告) |
| declarativeNetRequest | 网络 | 替代 webRequest的规则型请求拦截(推荐 V3) |
| proxy | 网络 | 修改浏览器代理设置 |
| cookies | 网络 | 读取和设置网站 Cookies(需配合 host 权限) |
| bookmarks | 界面 | 读取、添加、删除用户书签 |
| windows | 界面 | 管理浏览器窗口 |
| topSites | 浏览器 | 读取最常访问网站列表 |
| pageCapture | 浏览器 | 将页面保存为 MHTML 格式 |
| idle | 系统 | 检测用户是否空闲 |
| alarms | 系统 | 设置定时任务(周期性操作) |
| system.cpu | 系统 | 获取 CPU 使用情况(需额外授权) |
| system.memory | 系统 | 获取内存使用信息 |
| system.display | 系统 | 获取屏幕信息 |
| management | 高级 | 查看或卸载扩展程序(需额外授权) |
| debugger | 高危 | 调试页面(用户安装时需手动确认) |
| nativeMessaging | 高级 | 与本地程序通信(需额外安装原生宿主) |
3.2.2.3 拓展2matches 配置格式
语法:
<scheme>://<host><path>
-
scheme(协议):http, https, file, ftp, chrome-extension
-
host(域名):可以使用 * 通配符,如 *.google
-
path(路径):可以使用 * 通配任意路径
常用示例:
| 示例 | 匹配的页面 |
|---|---|
| "https://*/*" | 所有 HTTPS 页面 |
| "http://*.example/*" | example 及其所有子域的 HTTP 页面 |
| "*://mail.google/*" | Gmail 页面(支持 http 和 https) |
| "" | 所有网页(强权限,包括 http、https、file、ftp 等) |
| "file://*" | 所有本地文件(需用户勾选“允许访问文件网址”) |
配置示例:
"content_scripts": [
{
"matches": ["https://*.baidu/*", "https://*.google/*"],
"js": ["content.js"],
"run_at": "document_end"
}
]
3.3 background.js
在 Chrome 扩展中,background.js 是“后台脚本”,用于在浏览器后台常驻运行逻辑,处理事件监听、持久状态管理、消息通信等。
3.3.1 主要作用
| 作用 | 说明 |
|---|---|
| 📩 消息通信 | 与 content script、popup、options 页面通信 |
| 🧭 事件监听 | 监听浏览器事件,如 tabs.onUpdated,runtime.onMessage等 |
| 📌 状态管理 | 保持扩展的长期运行状态(如登录状态、缓存) |
| 🧠 定时任务 | 使用 chrome.alarms 实现周期性执行 |
| 🧱 动态注入脚本 | 使用 chrome.scripting.executeScript 向页面注入代码 |
| ⏱ 延迟加载功能 | 服务工作线程在需要时被唤醒处理事件(V3 特性) |
3.3.2 如何配置
在 manifest.json 中,通常通过如下方式声明:
"background": {
"service_worker": "background.js"
}
3.3.3 注意事项(V3)
-
不支持使用 window、document 等 DOM API
-
无法直接访问页面内容,需要通过 tabs 或 scripting 注入
-
服务工作线程非持续运行,空闲时会被系统回收(如无事件监听器)
3.4 content.js
content.js 是 Chrome 扩展中的 内容脚本(Content Script),作用是注入到网页中,可以直接读取和操作网页 DOM,就像你在控制台编写的脚本一样。
3.4.1 能做什么?
内容脚本是运行在网页上下文中的脚本,能够:
| ✅ 能做的 | 🚫 不能做的 |
|---|---|
| 操作页面 DOM、CSS | 访问 Chrome 扩展 API(如 chrome.tabs) |
| 获取网页上的文本、按钮、链接等 | 使用 alert、prompt弹窗(部分网站会拦截) |
| 监听用户点击、滚动等交互事件 | 使用 window.localStorage 可能被沙箱限制 |
| 向 background、popup 通信 | 直接访问后台页面变量 |
3.4.2 如何配置
在 manifest.json 中,通常通过如下方式声明:
"content_scripts": [
{
"matches": ["https://*/*"],
"js": ["content.js"],
"run_at": "document_end"
}
]
3.4.3 注意事项
-
content.js 无法使用像 chrome.tabs, chrome.runtime.onInstalled 等后台 API
-
每次页面刷新会重新注入脚本(除非 run_at 配置了 document_start)
-
若要访问页面中变量(如 window.xxx),可能需通过注入 script 标签的方式间接实现
3.4.4 与backgroud.js通信
content.js 向 background.js 发送消息:
chrome.runtime.sendMessage({ type: 'HELLO' }, (response) => {
console.log('收到回复:', response);
});
background.js 接收:
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === 'HELLO') {
sendResponse('你好,我是后台脚本');
}
});
3.5 popup.html
在 Chrome 扩展程序中,popup.html 是点击扩展图标时弹出的弹窗界面,可以视为一个迷你网页,它可以包含 HTML、CSS、JS,并可与 background.js、content.js 进行通信。
3.5.1 能做什么?
| 场景 | 示例 |
|---|---|
| 插件控制面板 | 打开/关闭功能、切换设置 |
| 实时信息展示 | 当前页面标题、剪贴板内容等 |
| 功能触发按钮 | 注入脚本、发消息、清理页面 |
| 输入表单 | 表单提交、关键字设置等 |
3.5.2 如何配置
在 manifest.json 中,通常通过如下方式声明:
"action": {
"default_popup": "popup.html",
"default_icon": "icons/icon-48.png"
}
3.5.3 注意事项
-
popup.html 是一个 独立页面,与网页和后台是隔离的
-
不会自动拥有网页上下文(如 DOM、变量),若需要获取需注入内容脚本
-
页面关闭速度快,操作需尽快完成或在 background 中延续处理逻辑
3.6 通信方式
Chrome 扩展的三个核心脚本:popup(弹窗页面)、background(后台脚本)和content script(内容脚本)运行在不同的上下文中,它们之间通过消息传递(Message Passing)机制来通信。
3.6.1 通信方式概览
+------------+ +---------------+ +--------------+
| popup.html| <-----> | background.js | <-----> | content.js |
+------------+ +---------------+ +--------------+
-
popup ↔ background:直接用 chrome.runtime.sendMessage / onMessage 双向通信
-
background ↔ content:用 chrome.tabs.sendMessage / onMessage 进行通信
-
popup ↔ content:不能直接通信,需通过 background 作为中转(或者使用 chrome.tabs.sendMessage,前提是 popup 访问的是对应 tab)
3.6.2 popup ↔ background 通信
发送消息:
// popup.js
chrome.runtime.sendMessage({ greeting: "hello from popup" }, (response) => {
console.log("background 回复:", response.reply);
});
接收消息:
// background.js
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.greeting === "hello from popup") {
sendResponse({ reply: "hi popup!" });
}
});
3.6.3 background ↔ content 通信
background 向 content 发送消息
// background.js
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { greeting: "hello from background" }, (response) => {
console.log("content 回复:", response.reply);
});
});
content 接收消息
// content.js
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.greeting === "hello from background") {
sendResponse({ reply: "hi background!" });
}
});
3.6.4 popup ↔ content 通信
3.6.4.1 直接传递
注意:这种方式要求 content script 已经注入对应页面。
popup 直接发送消息给 content
// popup.js
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { greeting: "hello from popup" }, (response) => {
console.log("content 回复:", response.reply);
});
});
content 接收消息
// content.js
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.greeting === "hello from popup") {
sendResponse({ reply: "hi popup!" });
}
});
3.6.4.2 通过background中转
popup ↔ background ↔ content 中转消息,步骤如下:
-
popup 发送消息给 background
-
background 转发消息给 content
-
content 处理后返回消息给 background
-
background 把结果返回给 popup
4. 简单的例子
这是一个简单的例子,提供改变页面背景颜色功能。示例内容使用 javascript 编写。
4.1 用例介绍
流程图
4.2 目录结构
hello-extension/
├── background.js
├── content/
│ └── content.js
├── icons/
│ └── icon.png
├── manifest.json
└── popup/
├── popup.html
└── popup.js
注:icon.png 像素大小为 128*128。
4.3 完整代码
manifest.json
{
"manifest_version": 3,
"name": "hello world",
"version": "1.0.0",
"description": "通过弹出页面改变网页背景颜色",
"permissions": [
"activeTab",
"tabs"
],
"host_permissions": [
"*://*/*"
],
"action": {
"default_popup": "popup/popup.html",
"default_icon": "icons/icon.png"
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content/content.js"],
"run_at": "document_idle"
}
],
"background": {
"service_worker": "background.js"
}
}
background.js,不参与事件消息传递。
chrome.runtime.onInstalled.addListener(() => {
console.log('扩展程序已安装');
});
content.js
console.log('内容脚本已加载于:', window.location.href);
function applyBackgroundColor(color, callback) {
if (document.body) {
console.log('Body 存在,应用颜色:', color);
document.body.style.backgroundColor = color + ' !important';
// 动态插入 style 标签以提高优先级
const style = document.createElement('style');
style.textContent = `body { background-color: ${color} !important; }`;
document.head.appendChild(style);
callback({ status: '背景颜色已更改' });
} else {
console.warn('Body 未找到,延迟尝试');
setTimeout(() => applyBackgroundColor(color, callback), 100);
}
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('收到消息:', message);
if (message.action === 'changeBackground') {
applyBackgroundColor(message.color, sendResponse);
}
return true;
});
popup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>背景颜色切换器</title>
<style>
body {
font-family: Arial, sans-serif, 'Microsoft YaHei', 'SimSun';
width: 300px;
padding: 10px;
text-align: center;
}
h2 {
font-size: 16px;
margin: 0 0 10px;
}
input[type="color"] {
width: 100%;
height: 40px;
margin: 10px 0;
}
button {
padding: 8px;
background-color: #4CAF50;
color: white;
border: none;
width: 100%;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
#error {
color: red;
font-size: 12px;
margin-top: 10px;
}
</style>
</head>
<body>
<h2>选择网页背景颜色</h2>
<input type="color" id="colorPicker" value="#ffffff">
<button id="changeColorBtn">应用颜色</button>
<div id="error"></div>
<script src="popup.js"></script>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', () => {
console.log('Popup 脚本已加载');
const colorPicker = document.getElementById('colorPicker');
const changeColorBtn = document.getElementById('changeColorBtn');
const errorDiv = document.getElementById('error');
changeColorBtn.addEventListener('click', () => {
const color = colorPicker.value;
console.log('选择颜色:', color);
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]) {
console.error('未找到活动标签页');
errorDiv.textContent = '错误:未找到活动标签页';
return;
}
console.log('向标签页发送消息:', tabs[0].id);
chrome.tabs.sendMessage(tabs[0].id, { action: 'changeBackground', color: color }, (response) => {
if (chrome.runtime.lastError) {
console.error('消息发送失败:', chrome.runtime.lastError.message);
errorDiv.textContent = '错误:无法连接到内容脚本,可能未注入';
return;
}
if (response) {
console.log('收到响应:', response);
errorDiv.textContent = response.status;
} else {
console.warn('未收到响应');
errorDiv.textContent = '错误:未收到内容脚本响应';
}
});
});
});
});
4.4 测试
将整个项目拖动到浏览器扩展程序界面。
打开 www.baidu ,点击‘扩展程序’
先选择颜色,再点击应用按钮。
效果
5. 后记
这是简单的使用原生js写的插件用例,后续我将介绍如何使用vue3开发。
6. 参考文档
- chrome extensions 开发文档
- Permissions 文档
版权声明:本文标题:【插件】小白也行!一篇文章带你上手Chrome扩展程序开发 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1765844370a3419646.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论