You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

谷歌浏览器插件开发详细教程

目录

  1. 插件概述
  2. 开发环境配置
  3. 插件基本结构
  4. 核心组件详解
  5. 常用API
  6. 实战案例
  7. 调试与发布

1. 插件概述

1.1 什么是Chrome扩展程序

Chrome扩展程序是基于Web技术HTML、CSS、JavaScript构建的小程序用于增强Chrome浏览器的功能。

1.2 扩展程序类型

  • 浏览器操作扩展:在工具栏添加图标
  • 页面操作扩展:针对特定页面生效
  • 内容脚本扩展:修改网页内容
  • 开发工具扩展:扩展开发者工具
  • 主题扩展:改变浏览器外观

1.3 扩展程序限制

  • 无法访问浏览器核心功能
  • 遵循同源策略
  • 需要明确的权限声明

2. 开发环境配置

2.1 必要工具

  • Chrome浏览器72+版本
  • 代码编辑器VS Code、Sublime等
  • 基础前端知识HTML、CSS、JavaScript

2.2 开发模式开启

  1. 打开Chrome浏览器
  2. 访问 chrome://extensions/
  3. 开启右上角"开发者模式"

3. 插件基本结构

3.1 最小化结构

my-extension/
├── manifest.json    # 配置文件
├── icon.png         # 扩展图标
├── popup.html       # 弹出页面
└── popup.js         # 弹出页面脚本

3.2 manifest.json 详解

{
  "manifest_version": 3,
  "name": "我的扩展程序",
  "version": "1.0.0",
  "description": "扩展程序描述",
  
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  
  "action": {
    "default_popup": "popup.html",
    "default_title": "点击查看详情",
    "default_icon": {
      "16": "icons/icon16.png",
      "32": "icons/icon32.png"
    }
  },
  
  "permissions": [
    "activeTab",
    "storage",
    "scripting"
  ],
  
  "host_permissions": [
    "https://*.example.com/*"
  ],
  
  "background": {
    "service_worker": "background.js"
  },
  
  "content_scripts": [
    {
      "matches": ["https://*.example.com/*"],
      "js": ["content.js"],
      "css": ["content.css"]
    }
  ],
  
  "web_accessible_resources": [{
    "resources": ["injected.js"],
    "matches": ["<all_urls>"]
  }]
}

4. 核心组件详解

4.1 后台脚本 (Background Script)

Manifest V3 使用 Service Worker

// background.js
chrome.runtime.onInstalled.addListener(() => {
  console.log('扩展已安装');
});

// 监听消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'getData') {
    sendResponse({ data: '处理后的数据' });
  }
  return true; // 保持消息通道开放
});

// 监听浏览器标签页更新
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete') {
    // 页面加载完成
  }
});

4.2 内容脚本 (Content Script)

// content.js
// 直接注入到网页上下文中

// 修改页面内容
document.body.style.backgroundColor = '#f0f0f0';

// 监听来自popup或background的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'extractText') {
    const text = document.body.innerText;
    sendResponse({ text: text.substring(0, 100) });
  }
});

// 向页面注入自定义脚本
const script = document.createElement('script');
script.src = chrome.runtime.getURL('injected.js');
document.head.appendChild(script);

4.3 弹出页面 (Popup)

<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      width: 300px;
      padding: 15px;
      font-family: Arial, sans-serif;
    }
    button {
      padding: 8px 16px;
      background: #4285f4;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <h3>我的扩展</h3>
  <button id="actionBtn">执行操作</button>
  <div id="result"></div>
  
  <script src="popup.js"></script>
</body>
</html>
// popup.js
document.getElementById('actionBtn').addEventListener('click', async () => {
  // 获取当前标签页
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  
  // 发送消息给内容脚本
  const response = await chrome.tabs.sendMessage(tab.id, { 
    action: 'getPageInfo' 
  });
  
  document.getElementById('result').textContent = 
    `页面标题: ${response.title}`;
});

// 使用存储API
chrome.storage.local.set({ key: 'value' }, () => {
  console.log('数据已保存');
});

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

5. 常用API

5.1 消息传递

// 发送消息
chrome.runtime.sendMessage(
  { action: 'doSomething', data: 'some data' },
  response => console.log('响应:', response)
);

// 标签页内通信
chrome.tabs.sendMessage(tabId, message, callback);

5.2 存储API

// 本地存储
chrome.storage.local.set({ key: 'value' });
chrome.storage.local.get(['key'], result => {});

// 同步存储(跨设备同步)
chrome.storage.sync.set({ settings: { theme: 'dark' } });

// 监听存储变化
chrome.storage.onChanged.addListener((changes, area) => {
  for (let key in changes) {
    console.log(`${key}${changes[key].oldValue} 变为 ${changes[key].newValue}`);
  }
});

5.3 标签页API

// 查询标签页
chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
  const currentTab = tabs[0];
});

// 创建新标签页
chrome.tabs.create({ url: 'https://example.com' });

// 更新标签页
chrome.tabs.update(tabId, { active: true });

// 执行脚本
chrome.scripting.executeScript({
  target: { tabId: tabId },
  func: () => {
    // 在页面中执行的代码
  }
});

5.4 通知API

chrome.notifications.create('id', {
  type: 'basic',
  iconUrl: 'icon.png',
  title: '通知标题',
  message: '通知内容'
});

6. 实战案例

案例1网页内容提取器

manifest.json

{
  "manifest_version": 3,
  "name": "网页内容提取器",
  "version": "1.0",
  "permissions": ["activeTab", "scripting"],
  "action": {
    "default_popup": "popup.html"
  }
}

popup.html

<!DOCTYPE html>
<html>
<body>
  <h3>内容提取</h3>
  <button id="extract">提取标题和链接</button>
  <div id="output"></div>
  <script src="popup.js"></script>
</body>
</html>

popup.js

document.getElementById('extract').addEventListener('click', async () => {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  
  const results = await chrome.scripting.executeScript({
    target: { tabId: tab.id },
    func: () => {
      // 提取页面所有链接
      const links = Array.from(document.querySelectorAll('a'))
        .map(a => ({
          text: a.textContent.trim(),
          href: a.href
        }))
        .filter(link => link.text && link.href);
      
      return {
        title: document.title,
        links: links.slice(0, 10) // 前10个链接
      };
    }
  });
  
  const output = document.getElementById('output');
  output.innerHTML = `
    <h4>${results[0].result.title}</h4>
    <ul>
      ${results[0].result.links.map(link => 
        `<li><a href="${link.href}" target="_blank">${link.text}</a></li>`
      ).join('')}
    </ul>
  `;
});

案例2自定义右键菜单

background.js

// 创建右键菜单
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: "searchGoogle",
    title: "使用Google搜索 '%s'",
    contexts: ["selection"]
  });
  
  chrome.contextMenus.create({
    id: "saveNote",
    title: "保存选中文本",
    contexts: ["selection"]
  });
});

// 处理菜单点击
chrome.contextMenus.onClicked.addListener((info, tab) => {
  switch (info.menuItemId) {
    case "searchGoogle":
      const query = encodeURIComponent(info.selectionText);
      chrome.tabs.create({ 
        url: `https://www.google.com/search?q=${query}` 
      });
      break;
      
    case "saveNote":
      chrome.storage.local.get(['notes'], (result) => {
        const notes = result.notes || [];
        notes.push({
          text: info.selectionText,
          url: tab.url,
          timestamp: new Date().toISOString()
        });
        chrome.storage.local.set({ notes });
      });
      break;
  }
});

7. 调试与发布

7.1 调试技巧

  1. 弹出页面调试:右键点击扩展图标 → "检查弹出内容"
  2. 后台脚本调试:进入扩展管理页面 → 点击"service worker"链接
  3. 内容脚本调试:在网页开发者工具 → Sources → Content scripts
  4. 网络请求查看:开发者工具 → Network → 筛选扩展请求

7.2 控制台日志

// 不同组件的日志查看位置
console.log('Background:', message);  // 后台脚本控制台
console.log('Content:', data);        // 网页控制台
console.log('Popup:', info);          // 弹出页面控制台

7.3 发布到Chrome网上应用店

  1. 准备工作

    • 准备各种尺寸的图标16x16, 48x48, 128x128, 512x512
    • 创建应用商店列表截图1280x800或640x400
    • 撰写详细描述和宣传图
  2. 打包扩展

    • 打开 chrome://extensions/
    • 点击"打包扩展程序"
    • 生成.crx文件和.pem私钥文件
  3. 提交审核

    • 访问Chrome开发者仪表板
    • 支付一次性注册费$5
    • 上传ZIP包并填写信息
    • 等待审核(通常需要几天)

7.4 常见问题解决

  1. 权限被拒绝

    • 检查manifest.json中的permissions
    • 确保host_permissions正确配置
  2. 消息传递失败

    • 检查组件是否已正确加载
    • 使用try-catch捕获错误
  3. 存储数据丢失

    • 使用chrome.storage替代localStorage
    • 重要数据定期备份
  4. 性能优化

    • 内容脚本使用延迟加载
    • 避免频繁的storage操作
    • 及时清理事件监听器

附录:实用资源

官方文档

开发工具

学习建议

  1. 从简单示例开始,逐步增加复杂度
  2. 充分理解Manifest V3的变化
  3. 注意安全性,避免恶意代码注入
  4. 考虑用户隐私,最小化权限请求
  5. 测试不同网站和场景的兼容性

提示:开发过程中,经常访问 chrome://extensions/ 页面进行加载、重载和调试。使用console.log()进行调试是最高效的方式之一。祝您开发顺利!