Chrome插件是使用HTML、CSS 和 JavaScript Web 技术构建的,开发者可以利用这些技术在浏览器中添加新功能、修改现有功能或者与网页进行交互。本文主要介绍如何使用Manifest V3快速搭建一个Chrome插件。
Manifest V3是Chrome插件的最新版本,相较于V2,主要改进以下几点:
- 更新manifest
manifest.json必须指定 V3。部分配置项进行了修改。 - 迁移到 Service Worker Service Worker 会替换扩展程序的后台或事件页面,以确保后台代码远离主线程,从而降低性能。此更改还将 DOM、窗口和某些扩展 API 调用移入屏幕外的文档中。
- 更新 API 调用 某些 API 调用需要替换为更现代的等效项。
- 替换阻止网络请求监听器 在 Manifest V2 中屏蔽或修改网络请求可能会显著降低性能,并导致需要过多访问敏感用户数据。借助
Declarative Net RequestAPI,扩展程序可以使用较少的权限来屏蔽或修改 Web 内容,而不会降低性能。 - 提高扩展程序安全性 Manifest V3 通过多种方式提高扩展程序的安全性。除了增强的内容安全政策之外,不再支持远程托管代码和任意字符串的执行。
基础配置manifest.json
开发chrome插件,最重要的文件 manifest.json,基础信息如下:
{
"name": "chrome-extension", // 插件名称
"version": "1.0", // 插件版本
"description": "chrome extension", // 插件描述
"manifest_version": 3, // manifest版本,涉及到api的变化,最新为3
"icons": { // 设置不同尺寸图标
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
}
}
当前目录结构
.
├── images
│ └── icon-16.png
│ └── icon-32.png
│ └── icon-48.png
│ └── icon-128.png
├── manifest.json
弹窗页面action
可以通过配置action实现点击图标触发插件
{
"name": "chrome-extension",
"version": "1.0",
"description": "chrome extension",
"manifest_version": 3,
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"action": {
"default_icon": { // 工具栏图标优先使用
"16": "images/default_icon-16.png",
"32": "images/default_icon-32.png",
"48": "images/default_icon-48.png",
"128": "images/default_icon-128.png"
},
"default_title": "Click", // 弹窗标题
"default_popup": "popup/popup.html" // 弹窗页面
},
}
创建popup.html, popup.css 和 popup.js 文件
.
├── images
│ └── icon-16.png
│ └── icon-32.png
│ └── icon-48.png
│ └── icon-128.png
│ └── default_icon-16.png
│ └── default_icon-32.png
│ └── default_icon-48.png
│ └── default_icon-128.png
├── manifest.json
├── popup
│ └── popup.html
│ └── popup.css
│ └── popup.js
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div class="hint">
<div>Thank you for using ChatAssistant!</div>
<button id="refresh-btn">refresh</button>
</div>
<script src="popup/popup.js"></script>
<script src="popup/popup.css"></script>
</body>
</html>
popup.css
.hint {
width: 200px;
}
popup.js
document.getElementById('refresh-btn').addEventListener('click', () => {
// 处理逻辑
chrome.tabs.reload(); // 网页刷新
window.close(); // 关闭弹窗
});
后台脚本background
后台处理脚本,在浏览器内跨Tab运行,可以完成跨域请求、网页截屏、弹出Chrome通知等重要浏览器事件的监听,但无法改变浏览器内容。
{
"name": "chrome-extension",
"version": "1.0",
"description": "chrome extension",
"manifest_version": 3,
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "background.js", // 脚本路径
"type": "module"
},
}
新建background.js
.
├── images
│ └── icon-16.png
│ └── icon-32.png
│ └── icon-48.png
│ └── icon-128.png
│ └── default_icon-16.png
│ └── default_icon-32.png
│ └── default_icon-48.png
│ └── default_icon-128.png
├── manifest.json
├── background.js
// 当插件首次安装或更新时,会触发此事件,并执行回调函数。
chrome.runtime.onInstalled.addListener(() => {
console.log('扩展插件已安装!');
});
// 在用户点击操作图标时触发。如果操作具有弹出式窗口(定义了default_popup),则不会触发此事件。
chrome.action.onClicked.addListener((tab: any) => {
chrome.tabs.sendMessage(tab.id, {
message: TIMING_WHEN_CLICK_EXTENSION_ICON,
});
});
内容脚本content_scripts
content_scripts在单Tab页隔离运行的内容脚本,不会与网页或其他扩展程序的内容脚本发生冲突,能够读取并更改网页内容,可以进行DOM操作。
{
"name": "chrome-extension",
"version": "1.0",
"description": "chrome extension",
"manifest_version": 3,
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "background.js",
"type": "module"
},
"content_scripts": [
{
"matches": [ // 指定要将此内容脚本注入哪些网页
"<all_urls>"
],
"css": [
"content/content.css"
],
"js": [
"content/content.js"
],
"run_at": "document_end" // 指定何时应将脚本注入到网页中
}
],
}
新建content.js,处理复杂页面逻辑
.
├── images
│ └── icon-16.png
│ └── icon-32.png
│ └── icon-48.png
│ └── icon-128.png
│ └── default_icon-16.png
│ └── default_icon-32.png
│ └── default_icon-48.png
│ └── default_icon-128.png
├── manifest.json
├── background.js
├── content
│ └── content.js
│ └── content.css
content.js
chrome.runtime.onMessage.addListener((request: any, sender: chrome.runtime.MessageSender, sendResponse: any) => {
// 接收到信息开始处理逻辑
});
权限permissions
需要在permissions中添加所需权限,这能帮助用户清楚为什需要此权限,且仅在必要的时候才运行扩展使用该权限。附可选权限 permissions
{
"name": "chrome-extension",
"version": "1.0",
"description": "chrome extension",
"manifest_version": 3,
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "background.js", // 脚本路径
"type": "module"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"css": [
"content.css"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"permissions": [
"tabs",
"activeTab"
],
}
可访问资源web_accessible_resources
使用 web_accessible_resources 清单属性声明向哪些来源公开哪些资源。此属性是声明资源访问规则的对象数组。每个对象都会列出一些扩展程序资源,并且必须为至少一个 matches 或 extension_ids 键提供一个值,以指明可以访问这些资源的来源。
{
"name": "chrome-extension",
"version": "1.0",
"description": "chrome extension",
"manifest_version": 3,
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "background.js", // 脚本路径
"type": "module"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"css": [
"content.css"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"permissions": [
"tabs",
"storage",
"scripting",
"activeTab"
],
"web_accessible_resources": [
{
"resources": [
"assets/*",
"static/index.js"
],
"matches": [
"<all_urls>"
]
}
],
}
通信
后台脚本和内容脚本之间的通信
发送方
background/popup
chrome.tabs.query({ active: true, currentWindow: true }, (result) => {
const tab = result[0];
chrome.tabs.sendMessage(tab.id, { message: 'start-panel' }, function (response) {
if (response?.message === 'success') {
window.close();
}
});
})
content_scripts
chrome.runtime.sendMessage({
message: TO_CREATE_CHAT,
}, (response) => {
console.log(response)
});
接收方
不管是background/popup/content_scripts接收事件是一样的
chrome.runtime.onMessage.addListener((request: any, sender: chrome.runtime.MessageSender, sendResponse: any) => {
// 处理逻辑
});
侧边栏sidePanel
将内容托管在浏览器侧边栏中的网页主要内容旁边,侧边栏只能主动唤醒,具有一定的交互限制
{
"name": "chrome-extension",
"version": "1.0",
"description": "chrome extension",
"manifest_version": 3,
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "background.js", // 脚本路径
"type": "module"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"css": [
"content.css"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"permissions": [
"tabs",
"storage",
"scripting",
"activeTab",
"sidePanel" // 添加权限
],
"side_panel": {
"default_path": "sidepanel.html" // 侧边栏页面
}
"web_accessible_resources": [
{
"resources": [
"assets/*",
"static/index.js"
],
"matches": [
"<all_urls>"
]
}
],
}
存储storage
chrome.storage可以实现在插件中数据共享。需要在permissions中添加storage权限
一般有三种模式:
-
chrome.storage.local数据会存储在本地,并会在移除扩展程序时清除。存储空间上限为 10 MB(在 Chrome 113 及更早版本中为 5 MB),但您可以通过请求
"unlimitedStorage"权限提高上限。建议使用storage.local存储大量数据 -
chrome.storage.sync如果启用同步,数据将同步到用户登录的任何 Chrome 浏览器。如果禁用,它的行为类似
storage.local -
chr``ome.storage.session在浏览器会话期间将数据保存在内存中。默认情况下,它不会暴露给内容脚本,但可以通过设置更改此行为
chrome.storage.session.setAccessLevel()。配额限制约为 10 MB
// 例子
chrome.storage.local.set({ key: value }).then(() => {
console.log("Value is set");
});
chrome.storage.local.get(["key"]).then((result) => {
console.log("Value is " + result.key);
});
chrome.storage.onChanged.addListener(
callback: function,
)
加载与调试
加载插件
打开 Chrome 浏览器的扩展程序管理页面
-
在 Chrome 浏览器中,点击右上角的三点菜单(更多),选择“更多工具” -> “扩展程序”。
-
直接在地址栏输入
chrome://extensions/并按回车键。
启用开发者模式
- 在扩展程序管理页面的右上角,找到并启用“开发者模式”开关。这将允许你加载未发布的插件和查看详细的调试信息。
加载插件
- 点击“加载已解压的扩展程序”按钮。
- 选择你创建的插件文件夹
my-chrome-extension,然后点击“选择文件夹”。 - 此时,你的插件将被加载到 Chrome 浏览器中。你应该能在扩展程序管理页面中看到你的插件图标。
更新插件
-
如果你对插件进行了修改,返回到扩展程序管理页面,点击“刷新”按钮来更新插件。
调试插件
调试后台脚本
- 在扩展程序管理页面,点击
Service Worker打开开发者工具。这就可以查看和调试后台脚本的日志、错误和其他信息。 - 你可以在控制台标签页中查看日志消息,使用断点调试代码。
调试内容脚本
- 内容脚本运行在网页的上下文中,因此需要打开相应的网页来调试它。
- 在开发者工具中,切换到源代码标签页,找到内容脚本文件并设置断点。
- 你可以在控制台标签页中查看内容脚本的日志和错误信息。
调试插件弹窗
- 点击浏览器工具栏中的插件图标,打开插件弹窗。
- 在插件弹窗打开的状态下,右键单击插件弹窗并选择检查打开开发者工具。
- 在开发者工具中,你可以查看和调试插件弹窗的
HTML、CSS和JavaScript文件。
结束语
以上是本人初学chrome插件的一些记录,希望对大家有所帮助,如果大家有疑问,欢迎留言讨论!