目录

一、 项目准备:你的第一个 Chrome 插件

1. 插件基础结构

2. 创建项目目录

3. manifest.json (核心配置)

4. 制作图标

5. popup.html 与 popup.js (用户交互界面)

6. background.js (后台服务与 API 调用)

7. content.js (与网页内容交互 - 可选)

二、 加载与调试插件

三、 前端工程化实践

1. 使用打包工具 (Vite/Webpack)

2. TypeScript 支持

四、 API 深度调用与安全

五、 常见插件类型与进阶

六、总结


如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

Chrome 插件开发,本质上是利用 Web 技术(HTML, CSS, JavaScript) 在浏览器环境中运行的一套小程序。它能让你定制浏览器行为、扩展网页功能、与外部 API 交互。

本指南将带你从零开始,创建一个具备前端工程化实践的 Chrome 插件,并深度调用 API。


一、 项目准备:你的第一个 Chrome 插件

1. 插件基础结构

一个最简单的 Chrome 插件包含以下核心文件:

  • manifest.json:插件的“身份证”,描述插件名称、版本、权限、脚本等。
  • popup.html:插件图标点击后弹出的窗口(可选)。
  • popup.js:控制 popup.html 行为的 JavaScript。
  • content.js:注入到目标网页执行的 JavaScript。
  • background.js:后台服务脚本,处理持久性任务、事件监听。
2. 创建项目目录

在你喜欢的目录下创建一个新文件夹,例如 my-chrome-extension

3. manifest.json (核心配置)

创建 manifest.json 文件,这是插件的入口。

{
  "manifest_version": 3, // 推荐使用 Manifest V3
  "name": "My Awesome Extension",
  "version": "1.0",
  "description": "A simple example Chrome Extension.",
  "permissions": [
    "activeTab", // 允许访问当前激活标签页
    "scripting", // 允许注入 content scripts
    "storage",   // 允许使用 chrome.storage API
    "https://api.example.com/*" // 允许访问特定 API 域名 (必填!否则无法跨域请求)
  ],
  "action": {
    "default_popup": "popup.html", // 点击插件图标时显示的文件
    "default_icon": {
      "16": "images/icon16.png", // 16x16 像素图标
      "48": "images/icon48.png", // 48x48 像素图标
      "128": "images/icon128.png" // 128x128 像素图标
    }
  },
  "background": {
    "service_worker": "background.js" // 后台服务脚本 (Manifest V3 使用 Service Worker)
  },
  "icons": {
    "16": "images/icon16.png",
    "48": "images/icon48.png",
    "128": "images/icon128.png"
  }
}

4. 制作图标

在项目根目录下创建 images 文件夹,并放置 icon16.pngicon48.pngicon128.png。你可以用任何图片编辑工具生成。

5. popup.html 与 popup.js (用户交互界面)

创建 popup.html

<!DOCTYPE html>
<html>
<head>
  <title>My Extension</title>
  <link rel="stylesheet" href="popup.css">
</head>
<body>
  <h1>Hello from My Extension!</h1>
  <button id="fetchDataBtn">Fetch Data from API</button>
  <div id="dataDisplay"></div>
  <script src="popup.js"></script>
</body>
</html>

创建 popup.js

document.addEventListener('DOMContentLoaded', function() {
  const fetchDataBtn = document.getElementById('fetchDataBtn');
  const dataDisplay = document.getElementById('dataDisplay');

  fetchDataBtn.addEventListener('click', async () => {
    dataDisplay.innerText = 'Loading...';
    try {
      // 调用 background.js 中的方法来获取数据,直接在 popup.js 中调用 chrome.runtime.sendMessage()
      // 涉及到跨域API请求,最好在 background.js 中处理,避免 CSP (Content Security Policy) 问题
      const response = await chrome.runtime.sendMessage({ action: "fetchApiData" });

      if (response.success) {
        dataDisplay.innerText = JSON.stringify(response.data, null, 2);
      } else {
        dataDisplay.innerText = `Error: ${response.error}`;
      }
    } catch (error) {
      dataDisplay.innerText = `Error sending message: ${error}`;
    }
  });
});

6. background.js (后台服务与 API 调用)

创建 background.js

// background.js

// 监听来自 popup.js 或 content.js 的消息
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.action === "fetchApiData") {
      fetchDataFromApi().then(data => {
        sendResponse({ success: true, data: data });
      }).catch(error => {
        sendResponse({ success: false, error: error.message });
      });
      return true; // 表示将异步发送响应
    }
    // 可以添加其他 action 的处理
  }
);

async function fetchDataFromApi() {
  const apiUrl = 'https://jsonplaceholder.typicode.com/todos/1'; // 示例 API
  const response = await fetch(apiUrl, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      // 如果 API 需要认证,在这里添加 Authorization header
      // 'Authorization': 'Bearer YOUR_API_KEY'
    }
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  return await response.json();
}

重要manifest.json 中的 permissions 必须包含你请求的 API 域名,否则 fetch 会报 CORS 错误。

7. content.js (与网页内容交互 - 可选)

如果你想操作当前网页的内容,可以创建 content.js

  • 在 manifest.json 中需要配置 content_scripts

// ... manifest.json ...
"content_scripts": [
  {
    "matches": ["<all_urls>"], // 作用于所有网页
    "js": ["content.js"]
  }
],
// ...

content.js 示例:

console.log("Content script injected!");

// 示例:修改网页标题
// document.title = "Modified by My Extension";

// 示例:通过 message passing 与 background.js 交互
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.action === "getPageTitle") {
      sendResponse({ title: document.title });
    }
  }
);

二、 加载与调试插件

  1. 打开 Chrome 扩展程序页面

    • 在 Chrome 地址栏输入 chrome://extensions/ 并回车。
  2. 启用开发者模式

    • 在页面右上角,打开“开发者模式”开关。
  3. 加载已解压的扩展程序

    • 点击左上角的“加载已解压的扩展程序”按钮。
    • 选择你创建的插件项目根目录(例如 my-chrome-extension)。
    • 你的插件会出现在扩展程序列表中。
  4. 调试

    • Popup 调试:在插件图标上右键,选择“检查 popup”。会打开一个类似 DevTools 的界面,可以调试 popup.js
    • Background 调试:在 chrome://extensions/ 页面,找到你的插件,点击“Service worker”的链接。会打开一个 DevTools 界面,可以调试 background.js
    • Content Script 调试:在目标网页中打开 DevTools,切换到 Console 或 Sources 标签页,可以看到 content.js 的输出和进行调试。

三、 前端工程化实践

当插件变得复杂,静态文件直接管理会混乱。

1. 使用打包工具 (Vite/Webpack)

安装

cd my-chrome-extension
npm init -y
npm install vite --save-dev
npm install @vitejs/plugin-legacy --save-dev # 可选,用于兼容老版本浏览器

配置 vite.config.js

import { defineConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';

export default defineConfig({
  plugins: [
    legacy({ // 兼容性配置
      targets: ['defaults', 'not IE 11']
    }),
    // Vite 默认会生成 index.html,但 Chrome 插件是 manifest.json 作为入口
    // 需要特殊处理,或者将 popup.html 作为 Vite 的入口
  ],
  build: {
    // 打包输出到插件根目录,并保持原有的 manifest.json
    outDir: 'dist', // 打包输出目录
    rollupOptions: {
      input: { // 定义入口文件
        popup: 'popup.html', // popup.js 会自动引入
        // background: 'background.js' // background.js 作为 service worker 不需要在这里单独入口
      },
      output: {
        assetFileNames: 'assets/[name].[hash][extname]', // 资源文件输出命名
        entryFileNames: '[name].js' // 入口文件输出命名
      }
    },
    emptyOutDir: true, // 清空输出目录
  },
  // 如果你的 manifest.json 引用了 .js 文件,直接放在根目录即可,Vite 会处理
  // 如果 manifest.json 放在 dist 目录,需要调整 manifest.json 中的路径
  // 最佳实践:manifest.json 保持在根目录,打包后手动复制到 dist
});

  • 调整 manifest.json
    • 将 popup.html 指向打包后的文件(如 dist/popup.html)。
    • background.js 通常也不需要 Vite 处理,直接放在根目录。
  • 运行构建

npm run build

  • 这会在 dist 文件夹生成打包后的文件。
  • 加载插件:在 chrome://extensions/ 页面,加载 dist 文件夹。
2. TypeScript 支持
  • 安装

npm install typescript --save-dev
npm install @types/chrome --save-dev # Chrome API 类型定义

  • 创建 .ts 文件:将 popup.jsbackground.jscontent.js 重命名为 .ts
  • 配置 tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020", // 现代 JS 目标
    "module": "ESNext",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "dist", // TS 文件编译输出到 dist
    "lib": ["ES2020", "DOM", "WebWorker"],
    "types": ["chrome", "node"] // 包含 chrome 类型
  },
  "include": ["src/**/*"], // TS 源文件目录
  "exclude": ["node_modules", "dist"] // 排除目录
}

  • 修改 Vite 配置
    • 安装 @vitejs/plugin-vue 或 @vitejs/plugin-react(如果你使用 Vue/React)。
    • 调整 vite.config.js,指向 src 目录作为入口。

四、 API 深度调用与安全

  1. 跨域请求(CORS)
    • manifest.json 的 permissions 中必须声明允许访问的 API 域名。
    • "https://api.example.com/*" 这种声明是强制的。
    • 如果你要访问 chrome:// 内的 API,是不允许的。
  2. 用户数据敏感性
    • 如果 API 调用涉及到用户敏感信息(如用户 ID、个人配置),切勿直接在 content.js 中进行
    • 最佳实践:所有敏感 API 调用都应放在 background.js 中。content.js 负责收集网页信息,通过 chrome.runtime.sendMessage 发送给 background.js,由 background.js 处理 API 请求,然后将结果 sendResponse 回去。
  3. API 密钥管理
    • 绝不硬编码:将 API Key 硬编码在插件的 JavaScript 文件中是极其危险的,用户可以轻易地在插件源码中看到。
    • 推荐策略
      • 用户设置页面:为插件创建一个 options.html(在 manifest.json 中配置 options_page)。让用户在插件的设置页面输入 API Key,然后通过 chrome.storage.sync 或 chrome.storage.local 保存。
      • 背景脚本获取background.js 在需要时从 chrome.storage 读取 API Key。
  4. 错误处理与用户反馈
    • API 请求失败时,要给用户清晰的反馈(例如在 popup 中显示错误信息)。
    • 使用 try...catch 块处理 fetch 错误,并向用户说明原因。

五、 常见插件类型与进阶

  1. 数据抓取类content.js 负责从网页 DOM 中提取数据,background.js 负责将数据发送到后端 API。
  2. 网页增强类content.js 动态修改页面样式或内容,background.js 负责监听某些事件(如标签页切换、书签更新)。
  3. 快速访问类popup.html 提供快捷链接、搜索框, popup.js 通过 chrome.tabs.create 或 chrome.runtime.sendMessage 与后台交互。

六、总结

Chrome 插件开发是一个融合了前端工程化与浏览器 API 调用的过程。

  • Manifest V3 是趋势,学习它的生命周期和权限管理。
  • API 调用放在 background.js,并优先使用 chrome.storage 管理敏感信息。
  • 拥抱前端工程化工具(Vite/TypeScript),让你的插件开发更高效、更健壮。
  • 永远要考虑用户体验和安全,尤其是 API Key 的管理。

通过以上步骤,你已经构建了一个具备基本 API 调用能力、支持前端工程化的 Chrome 插件。从这里开始,你可以探索更多浏览器 API,实现更丰富的功能!

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐