Browser Extension Development Skill
跨浏览器插件开发技能,支持Chrome、Firefox、Edge、Safari,包含Manifest V3规范、自动化构建、质量保证和发布流程。
功能特性
- ✅ 跨浏览器兼容 (Chrome/Firefox/Edge/Safari)
- ✅ Manifest V3 标准支持
- ✅ 自动化构建和打包
- ✅ 多浏览器同时测试
- ✅ 代码质量检查和优化
- ✅ 自动发布到商店
- ✅ 插件模板和脚手架
- ✅ 调试和性能分析工具
- ✅ 国际化支持
- ✅ 安全审计和合规检查
支持的浏览器
| 浏览器 | 版本要求 | 格式 | 商店 | |--------|----------|------|------| | Chrome | 88+ | Manifest V3 | Chrome Web Store | | Firefox | 109+ | Manifest V3 | Firefox Add-ons | | Edge | 88+ | Manifest V3 | Microsoft Edge Add-ons | | Safari | 14+ | Safari Web Extension | Mac App Store |
工作流程
Step 1: 选择插件类型
第1步:选择插件类型
[1] 📌 侧边栏插件 - 侧边栏界面
[2] 🎯 弹出窗口插件 - Popup界面
[3] 📄 内容脚本插件 - 注入网页
[4] 🔧 工具栏插件 - Browser Action
[5] 🎨 主题插件 - 浏览器主题
[6] 📋 背景脚本插件 - 后台服务
[7] 🚀 全功能插件 - 组合类型
Step 2: 配置插件信息
第2步:配置插件信息
插件名称: [输入名称]
版本号: [1.0.0]
描述: [输入描述]
作者: [输入作者]
权限: [选择权限列表]
Step 3: 选择功能模块
第3步:选择功能模块
[1] 🔔 通知系统
[2] 💾 本地存储
[3] 🌐 网络请求拦截
[4] 📸 截图功能
[5] 📋 剪贴板操作
[6] 🔍 页面分析
[7] 📊 数据统计
[8] ⚙️ 选项页面
Step 4: 选择UI框架
第4步:选择UI框架
[1] 🎨 原生HTML/CSS/JS
[2] ⚛️ React
[3] 💚 Vue.js
[4] 🔷 Svelte
[5] 🎯 Solid.js
[6] 📦 Web Components
Step 5: 生成项目结构
根据选择生成完整的项目结构,包含所有必要的配置文件和模板代码。
Step 6: 开发和调试
使用提供的开发工具进行实时调试和测试。
Step 7: 构建和打包
自动构建所有浏览器版本的插件包。
Step 8: 质量检查
运行代码质量检查、安全审计和性能测试。
Step 9: 发布部署
一键发布到各个浏览器商店。
项目结构模板
基础模板
my-extension/
├── src/
│ ├── manifest.json # Chrome/Edge manifest
│ ├── manifest.firefox.json # Firefox manifest
│ ├── manifest.safari.json # Safari manifest
│ ├── background/
│ │ └── service-worker.js # Background script
│ ├── content/
│ │ ├── content.js # Content script
│ │ └── content.css # Content styles
│ ├── popup/
│ │ ├── popup.html # Popup UI
│ │ ├── popup.js # Popup logic
│ │ └── popup.css # Popup styles
│ ├── options/
│ │ ├── options.html # Options page
│ │ ├── options.js # Options logic
│ │ └── options.css # Options styles
│ ├── sidebar/
│ │ ├── sidebar.html # Sidebar UI
│ │ ├── sidebar.js # Sidebar logic
│ │ └── sidebar.css # Sidebar styles
│ ├── icons/
│ │ ├── icon16.png
│ │ ├── icon48.png
│ │ └── icon128.png
│ └── _locales/
│ ├── en/
│ │ └── messages.json
│ └── zh_CN/
│ └── messages.json
├── scripts/
│ ├── build.js # Build script
│ ├── watch.js # Watch script
│ └── publish.js # Publish script
├── tests/
│ ├── unit/
│ └── integration/
├── docs/
├── package.json
├── webpack.config.js
└── README.md
权限系统
常用权限
{
"permissions": [
"activeTab", // 当前标签页
"tabs", // 标签页管理
"storage", // 本地存储
"notifications", // 通知
"clipboardRead", // 读取剪贴板
"clipboardWrite", // 写入剪贴板
"downloads", // 下载管理
"webRequest", // 网络请求
"cookies", // Cookie管理
"history", // 浏览历史
"bookmarks", // 书签管理
"contextMenus", // 右键菜单
"management", // 插件管理
"scripting", // 脚本注入
"sidePanel" // 侧边栏
],
"host_permissions": [
"https://*/*", // 所有HTTPS网站
"http://*/*", // 所有HTTP网站
"*://*.example.com/*" // 特定网站
]
}
API使用指南
存储API
// 保存数据
chrome.storage.local.set({ key: value });
// 读取数据
chrome.storage.local.get(['key'], (result) => {
console.log(result.key);
});
// 监听变化
chrome.storage.onChanged.addListener((changes, namespace) => {
for (let key in changes) {
let storageChange = changes[key];
console.log(key, storageChange.oldValue, storageChange.newValue);
}
});
标签页API
// 获取当前标签页
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
let currentTab = tabs[0];
});
// 创建新标签页
chrome.tabs.create({url: 'https://example.com'});
// 更新标签页
chrome.tabs.update(tabId, {url: 'https://example.com'});
// 注入内容脚本
chrome.scripting.executeScript({
target: {tabId: tabId},
files: ['content.js']
});
通知API
// 创建通知
chrome.notifications.create('notification-id', {
type: 'basic',
iconUrl: 'icon.png',
title: '标题',
message: '内容'
});
// 监听点击
chrome.notifications.onClicked.addListener((notificationId) => {
console.log('通知被点击:', notificationId);
});
网络请求API
// 监听请求
chrome.webRequest.onBeforeRequest.addListener(
(details) => {
console.log('请求:', details.url);
return {cancel: false};
},
{urls: ["<all_urls>"]},
["blocking"]
);
// 修改请求头
chrome.webRequest.onBeforeSendHeaders.addListener(
(details) => {
details.requestHeaders.push({
name: 'X-Custom-Header',
value: 'value'
});
return {requestHeaders: details.requestHeaders};
},
{urls: ["<all_urls>"]},
["blocking", "requestHeaders"]
);
跨浏览器兼容性处理
条件代码
// 检测浏览器
const isChrome = typeof chrome !== 'undefined' && chrome.runtime;
const isFirefox = typeof browser !== 'undefined';
const isSafari = typeof safari !== 'undefined';
// 使用适配器模式
if (isChrome) {
// Chrome/Edge代码
chrome.runtime.sendMessage({action: 'getData'});
} else if (isFirefox) {
// Firefox代码
browser.runtime.sendMessage({action: 'getData'});
} else if (isSafari) {
// Safari代码
safari.extension.dispatchMessage('getData');
}
统一API封装
// utils/browser-api.js
export const browserAPI = (() => {
if (typeof chrome !== 'undefined' && chrome.runtime) {
return chrome;
} else if (typeof browser !== 'undefined') {
return browser;
}
throw new Error('Unsupported browser');
})();
// 使用
browserAPI.storage.local.set({key: value});
browserAPI.tabs.query({active: true, currentWindow: true});
构建配置
Webpack配置
// webpack.config.js
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: {
background: './src/background/service-worker.js',
content: './src/content/content.js',
popup: './src/popup/popup.js',
options: './src/options/options.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]/[name].js'
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
plugins: [
new CopyPlugin({
patterns: [
{from: 'src/manifest.json', to: 'manifest.json'},
{from: 'src/icons', to: 'icons'},
{from: 'src/_locales', to: '_locales'},
{from: 'src/popup/popup.html', to: 'popup/popup.html'},
{from: 'src/options/options.html', to: 'options/options.html'},
{from: 'src/sidebar/sidebar.html', to: 'sidebar/sidebar.html'}
]
}),
new MiniCssExtractPlugin({
filename: '[name]/[name].css'
})
]
};
质量保证
代码检查规则
{
"extends": [
"eslint:recommended",
"plugin:chrome-extension/recommended",
"plugin:mozilla/recommended"
],
"rules": {
"no-unused-vars": "error",
"no-undef": "error",
"camelcase": "warn",
"consistent-return": "error",
"no-eval": "error",
"no-implied-eval": "error"
}
}
测试框架
// Jest配置
module.exports = {
testEnvironment: 'jsdom',
setupFiles: ['./tests/setup.js'],
testMatch: ['**/tests/**/*.test.js'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80
}
}
};
发布流程
Chrome Web Store
- 打包为.zip文件
- 登录Chrome Web Store开发者控制台
- 上传并填写插件信息
- 提交审核
Firefox Add-ons
- 使用web-ext工具打包
- 登录Firefox Developer Hub
- 上传并填写插件信息
- 提交审核
Microsoft Edge Add-ons
- 打包为.zip文件
- 登录Microsoft Partner Center
- 上传并填写插件信息
- 提交审核
Safari App Store
- 使用Xcode打包
- 提交到App Store Connect
- 填写插件信息
- 提交审核
调试技巧
Chrome调试
chrome://extensions/开启开发者模式- 检查后台页面控制台
- 使用DevTools检查内容脚本
- 查看Network面板的请求
Firefox调试
about:debugging#/runtime/this-firefox- 检查后台脚本
- 使用浏览器控制台
- 查看存储数据
Edge调试
edge://extensions/开启开发者模式- 类似Chrome的调试方式
性能优化建议
- 减少权限: 只请求必要的权限
- 延迟加载: 非关键功能延迟加载
- 缓存数据: 合理使用storage缓存
- 优化网络: 批量请求,减少API调用
- 内存管理: 及时清理不需要的监听器
- 代码分割: 使用动态import分割代码
安全最佳实践
- 内容安全策略: 配置严格的CSP
- 输入验证: 验证所有用户输入
- HTTPS优先: 优先使用HTTPS
- 最小权限: 只请求必要权限
- 数据加密: 敏感数据加密存储
- 定期更新: 及时更新依赖
依赖安装
npm install
直接运行脚本
# 开发模式
npm run dev
# 构建所有浏览器版本
npm run build
# 构建特定浏览器
npm run build:chrome
npm run build:firefox
npm run build:edge
npm run build:safari
# 测试
npm test
# 代码检查
npm run lint
# 发布
npm run publish
注意事项
- Chrome和Edge使用相同的Manifest V3格式
- Firefox使用Manifest V3但有一些差异
- Safari需要特殊的适配
- 不同浏览器的API实现可能有差异
- 权限声明需要根据实际需求调整
- 测试时需要在不同浏览器中验证
验证
生成后检查:
- 项目结构是否完整
- Manifest文件是否正确
- 构建脚本是否可执行
- 代码质量是否达标
- 跨浏览器兼容性是否良好
微信扫一扫