Chrome Extension Boilerplate React Vite:浏览器自动化控制

【免费下载链接】chrome-extension-boilerplate-react-vite Chrome Extension Boilerplate with React + Vite + Typescript 【免费下载链接】chrome-extension-boilerplate-react-vite 项目地址: https://gitcode.com/GitHub_Trending/ch/chrome-extension-boilerplate-react-vite

你是否还在为手动操作浏览器重复任务而烦恼?本文将带你使用Chrome Extension Boilerplate React Vite构建高效浏览器自动化工具,通过React组件注入、内容脚本和侧边栏面板实现网页数据抓取、自动表单填写等实用功能。读完本文,你将掌握扩展开发全流程,从环境搭建到自动化脚本编写,让浏览器为你高效工作。

项目概述

该项目是基于React、TypeScript和Vite构建的Chrome/Firefox扩展开发模板,通过Turborepo提升构建速度和开发体验。它支持Manifest V3标准,提供热模块重载(HMR)、国际化(i18n)和跨页面状态管理等核心功能,特别适合开发需要与网页内容交互的自动化工具。

项目核心优势:

  • 基于React 18和TypeScript的类型安全开发环境
  • Vite驱动的极速热重载,开发效率提升300%
  • 模块化架构支持内容脚本、侧边栏和弹出窗口等多界面形态
  • 内置存储管理模块实现跨页面数据共享

环境准备与安装

开发环境配置

  1. 克隆项目仓库:
git clone https://gitcode.com/GitHub_Trending/ch/chrome-extension-boilerplate-react-vite
cd chrome-extension-boilerplate-react-vite
  1. 安装依赖(需Node.js 16+和pnpm):
npm install -g pnpm
pnpm install
  1. 启动开发服务器:
pnpm dev  # Chrome开发模式
# 或
pnpm dev:firefox  # Firefox开发模式
  1. 加载扩展到浏览器:
    • Chrome:访问chrome://extensions,启用"开发者模式",点击"加载已解压的扩展程序",选择项目中的dist目录
    • Firefox:访问about:debugging#/runtime/this-firefox,点击"临时载入附加组件",选择dist/manifest.json文件

项目结构解析

项目采用Turborepo管理的多包架构,核心代码组织如下:

chrome-extension/          # 扩展核心配置
├── manifest.ts            # 扩展清单配置[chrome-extension/manifest.ts](https://link.gitcode.com/i/c10a207e74506274d83d0e771473dbfd)
└── public/                # 静态资源
    ├── icon-128.png       # 扩展图标[chrome-extension/public/icon-128.png](https://link.gitcode.com/i/33bcb709920e9290054b9139c95bc0ab)
    └── icon-34.png        # 工具栏图标[chrome-extension/public/icon-34.png](https://link.gitcode.com/i/4e8d3a7f27b6e663039cb0fb03978b5a)

pages/                     # 扩展界面组件
├── content/               # 内容脚本[pages/content/](https://link.gitcode.com/i/ed1fd0bf201151b7d604b4b7ea25e861)
├── side-panel/            # 侧边栏面板[pages/side-panel/](https://link.gitcode.com/i/77270504ed797302eed48bc327d53005)
└── popup/                 # 弹出窗口[pages/popup/](https://link.gitcode.com/i/788fe38b73b3528ea62fb93225093943)

packages/                  # 共享功能模块
├── storage/               # 存储管理[packages/storage/](https://link.gitcode.com/i/1a4f3803efa10c4f9e303a8eca6b5727)
├── hmr/                   # 热重载插件[packages/hmr/](https://link.gitcode.com/i/d6bc1ff726597ba287d66bf24ffd3166)
└── shared/                # 共享工具函数[packages/shared/](https://link.gitcode.com/i/0ced7388c9c14c1ad6787c34c7087cc6)

自动化控制核心功能实现

内容脚本注入与网页操作

内容脚本是实现网页自动化的核心,它们运行在目标网页上下文中,可直接操作DOM元素。项目中内容脚本组织在pages/content目录,支持按URL匹配注入不同脚本。

基础内容脚本示例

创建pages/content/src/matches/example/index.ts实现自动表单填写:

// 匹配example.com域名的内容脚本
export default function runAutomation() {
  // 等待页面加载完成
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initAutomation);
  } else {
    initAutomation();
  }
}

function initAutomation() {
  // 自动填写登录表单
  const usernameInput = document.querySelector<HTMLInputElement>('input[name="username"]');
  const passwordInput = document.querySelector<HTMLInputElement>('input[name="password"]');
  const submitButton = document.querySelector<HTMLButtonElement>('button[type="submit"]');
  
  if (usernameInput && passwordInput && submitButton) {
    usernameInput.value = 'auto_filled@example.com';
    passwordInput.value = 'secure_password_123';
    
    // 3秒后自动提交
    setTimeout(() => {
      submitButton.click();
      console.log('表单已自动提交');
    }, 3000);
  }
}
配置内容脚本注入规则

修改chrome-extension/manifest.ts配置内容脚本注入规则:

// 在manifest.ts的content_scripts数组中添加
{
  matches: ['https://example.com/login*'],  // 匹配登录页面
  js: ['content/example.iife.js'],          // 注入我们的自动化脚本
  run_at: 'document_idle'                   // 文档加载完成后执行
}

侧边栏面板开发

侧边栏提供了与用户交互的界面,可通过它控制自动化流程。项目中pages/side-panel目录包含侧边栏组件,使用React开发。

侧边栏组件示例

修改pages/side-panel/src/SidePanel.tsx添加自动化控制按钮:

import React, { useState } from 'react';
import { useStorage } from '@extension/shared';  // 导入存储钩子

const SidePanel: React.FC = () => {
  const [status, setStatus] = useState('idle');
  const { getStorage, setStorage } = useStorage();
  
  // 启动自动化任务
  const startAutomation = async () => {
    setStatus('running');
    
    // 获取当前激活标签页
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    
    if (tab.id) {
      // 向内容脚本发送消息
      chrome.tabs.sendMessage(tab.id, { 
        action: 'start_automation',
        config: await getStorage('automation_config')
      }, (response) => {
        setStatus(response.success ? 'completed' : 'error');
      });
    }
  };
  
  return (
    <div className="p-4 w-64">
      <h2 className="text-lg font-bold mb-4">网页自动化助手</h2>
      
      <div className="mb-4">
        <label className="block mb-2">自动化状态: {status}</label>
        <button 
          onClick={startAutomation}
          disabled={status === 'running'}
          className="w-full bg-blue-500 text-white py-2 px-4 rounded"
        >
          {status === 'running' ? '运行中...' : '启动自动化'}
        </button>
      </div>
      
      {/* 配置保存示例 */}
      <div>
        <h3 className="font-medium mb-2">自动化配置</h3>
        <textarea 
          className="w-full h-24 p-2 border rounded"
          placeholder="输入自动化规则JSON..."
          onChange={(e) => {
            try {
              setStorage('automation_config', JSON.parse(e.target.value));
            } catch (err) {
              console.error('配置格式错误', err);
            }
          }}
        ></textarea>
      </div>
    </div>
  );
};

export default SidePanel;

跨页面通信与状态管理

扩展的不同组件(侧边栏、弹出窗口、背景页)通过Chrome API进行通信,配合存储模块实现状态共享。项目提供的@extension/storage包简化了存储操作:

// 保存数据到本地存储
import { useStorage } from '@extension/shared/lib/hooks/use-storage.tsx';

const { setStorage, getStorage } = useStorage();

// 保存自动化配置
await setStorage('auto_fill_rules', {
  usernameSelector: 'input[name="user"]',
  passwordSelector: 'input[name="pass"]',
  submitSelector: 'button[type="submit"]'
});

// 获取配置
const rules = await getStorage('auto_fill_rules');

背景服务工作线程(chrome-extension/src/background/index.ts)负责协调不同组件间的通信:

// 监听来自内容脚本的消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'automation_completed') {
    // 显示通知
    chrome.notifications.create({
      type: 'basic',
      iconUrl: 'icon-128.png',
      title: '自动化完成',
      message: `已处理 ${message.count} 条数据`
    });
    
    // 记录操作日志
    chrome.storage.local.set({
      lastAutomation: new Date().toISOString(),
      totalActions: message.count
    });
    
    sendResponse({ success: true });
  }
});

实战案例:网页数据抓取工具

以下是一个完整的自动化数据抓取工具实现,它从电商网站提取产品信息并保存到本地CSV文件。

1. 内容脚本实现数据提取

创建pages/content/src/matches/ecommerce/index.ts

// 电商网站数据提取脚本
export default function extractProductData() {
  // 等待页面加载完成
  window.addEventListener('load', () => {
    // 检查是否是产品列表页
    if (window.location.pathname.includes('/products')) {
      extractProductList();
    } 
    // 检查是否是产品详情页
    else if (window.location.pathname.includes('/product/')) {
      extractProductDetails();
    }
  });
  
  // 监听来自扩展的消息
  chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.action === 'extract_data') {
      switch (message.target) {
        case 'list':
          sendResponse(extractProductList());
          break;
        case 'details':
          sendResponse(extractProductDetails());
          break;
        default:
          sendResponse({ error: '未知目标' });
      }
    }
  });
  
  // 提取产品列表
  function extractProductList() {
    const products = Array.from(document.querySelectorAll('.product-item')).map(item => ({
      title: item.querySelector('.product-title')?.textContent?.trim(),
      price: item.querySelector('.product-price')?.textContent?.trim(),
      url: item.querySelector('a')?.href,
      image: item.querySelector('img')?.src
    })).filter(Boolean);
    
    return {
      type: 'product_list',
      count: products.length,
      data: products,
      extractedAt: new Date().toISOString()
    };
  }
  
  // 提取产品详情
  function extractProductDetails() {
    return {
      type: 'product_details',
      data: {
        title: document.querySelector('h1.product-title')?.textContent?.trim(),
        price: document.querySelector('.product-price')?.textContent?.trim(),
        description: document.querySelector('.product-description')?.textContent?.trim(),
        specifications: Array.from(document.querySelectorAll('.spec-row')).reduce((specs, row) => {
          const key = row.querySelector('.spec-name')?.textContent?.trim();
          const value = row.querySelector('.spec-value')?.textContent?.trim();
          if (key && value) specs[key] = value;
          return specs;
        }, {}),
        images: Array.from(document.querySelectorAll('.product-image img')).map(img => img.src)
      },
      extractedAt: new Date().toISOString()
    };
  }
}

2. 侧边栏控制面板

修改pages/side-panel/src/SidePanel.tsx添加数据抓取控制界面:

import React, { useState, useEffect } from 'react';
import { useStorage } from '@extension/shared/lib/hooks/use-storage.tsx';

const SidePanel: React.FC = () => {
  const [status, setStatus] = useState('ready');
  const [extractedData, setExtractedData] = useState(null);
  const [currentTab, setCurrentTab] = useState(null);
  const { getStorage, setStorage } = useStorage();
  
  // 获取当前标签页信息
  useEffect(() => {
    chrome.tabs.query({ active: true, currentWindow: true })
      .then(tabs => setCurrentTab(tabs[0]));
  }, []);
  
  // 提取列表数据
  const extractListData = async () => {
    if (!currentTab?.id) return;
    
    setStatus('extracting');
    try {
      const result = await chrome.tabs.sendMessage(currentTab.id, {
        action: 'extract_data',
        target: 'list'
      });
      
      setExtractedData(result);
      setStatus('completed');
      
      // 保存到存储
      await setStorage('extracted_data', {
        url: currentTab.url,
        timestamp: new Date().toISOString(),
        data: result
      });
      
      // 下载CSV文件
      downloadCSV(result.data);
    } catch (err) {
      setStatus('error');
      console.error('提取失败:', err);
    }
  };
  
  // 导出为CSV文件
  const downloadCSV = (products) => {
    const headers = ['标题', '价格', 'URL', '图片'];
    const rows = [
      headers.join(','),
      ...products.map(p => [
        `"${p.title?.replace(/"/g, '""')}"`,
        `"${p.price?.replace(/"/g, '""')}"`,
        `"${p.url?.replace(/"/g, '""')}"`,
        `"${p.image?.replace(/"/g, '""')}"`
      ].join(','))
    ];
    
    const csvContent = rows.join('\n');
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `products_${new Date().toISOString().slice(0,10)}.csv`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };
  
  return (
    <div className="p-4 w-72">
      <h2 className="text-lg font-bold mb-4">电商数据助手</h2>
      
      <div className="mb-4 p-3 bg-gray-100 rounded">
        <p className="text-sm mb-2">当前页面: {currentTab?.title?.slice(0, 30)}...</p>
        <p className="text-xs text-gray-500 mb-3">{currentTab?.url?.slice(0, 50)}...</p>
        
        <button 
          onClick={extractListData}
          disabled={status === 'extracting'}
          className="w-full bg-green-500 text-white py-2 px-4 rounded disabled:bg-gray-400"
        >
          {status === 'extracting' ? '提取中...' : '提取产品列表'}
        </button>
      </div>
      
      {extractedData && (
        <div className="mt-4 p-3 bg-green-50 border border-green-200 rounded">
          <h3 className="font-medium text-green-700 mb-2">提取结果</h3>
          <p className="text-sm">共找到 {extractedData.count} 个产品</p>
          <button 
            onClick={() => downloadCSV(extractedData.data)}
            className="mt-2 text-sm text-blue-600"
          >
            下载CSV文件
          </button>
        </div>
      )}
      
      {status === 'error' && (
        <div className="mt-4 p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm">
          提取失败,请确保在支持的电商页面上使用此功能
        </div>
      )}
    </div>
  );
};

export default SidePanel;

3. 更新扩展清单

确保chrome-extension/manifest.ts中包含必要的权限和内容脚本配置:

// 在manifest.ts的content_scripts数组中添加
{
  matches: ['https://*.example-ecommerce.com/products*'],
  js: ['content/ecommerce.iife.js']
}

// 在permissions数组中确保包含
permissions: ['storage', 'scripting', 'tabs', 'downloads', 'notifications'],
host_permissions: ['<all_urls>']

调试与部署

开发调试技巧

  1. 内容脚本调试

    • Chrome:在开发者工具的"Sources"面板中,展开"Content scripts"找到你的脚本
    • 使用chrome.devtools.inspectedWindow.eval()在页面上下文中执行代码
  2. 背景页调试

    • Chrome:访问chrome://extensions,点击扩展的"Service Worker"链接
    • Firefox:访问about:debugging#/runtime/this-firefox,点击"检查"按钮
  3. 热重载问题排查: 如果热重载失效,尝试重启开发服务器并重新加载扩展:

    pnpm dev --force  # 强制重新构建
    

生产构建与发布

  1. 构建生产版本:
pnpm build  # Chrome生产构建
# 或
pnpm build:firefox  # Firefox生产构建
  1. 打包为ZIP文件:
pnpm zip  # 生成dist-zip/extension-YYYYMMDD-HHmmss.zip
  1. 发布到应用商店:

高级功能与扩展

自动化任务调度

使用chrome.alarmsAPI实现定时自动化任务:

// 在background/index.ts中添加
chrome.alarms.create('daily-scrape', {
  when: Date.now() + 60000,  // 1分钟后首次执行
  periodInMinutes: 1440      // 每天执行一次
});

chrome.alarms.onAlarm.addListener(alarm => {
  if (alarm.name === 'daily-scrape') {
    // 打开目标页面并执行自动化
    chrome.tabs.create({ url: 'https://example-ecommerce.com/new-products' })
      .then(tab => {
        // 等待页面加载后注入脚本
        setTimeout(() => {
          chrome.scripting.executeScript({
            target: { tabId: tab.id },
            files: ['content/ecommerce.iife.js']
          }).then(() => {
            chrome.tabs.sendMessage(tab.id, { action: 'auto_scrape_and_save' });
          });
        }, 5000);
      });
  }
});

用户配置界面

利用项目提供的Options页面(pages/options/)创建用户配置界面,让用户自定义自动化规则:

// pages/options/src/Options.tsx示例
import React from 'react';
import { useStorage } from '@extension/shared/lib/hooks/use-storage.tsx';

const Options: React.FC = () => {
  const { getStorage, setStorage } = useStorage();
  const [selectors, setSelectors] = React.useState({
    title: 'h1.product-title',
    price: '.product-price',
    description: '.product-description'
  });
  
  React.useEffect(() => {
    getStorage('custom_selectors').then(data => {
      if (data) setSelectors(data);
    });
  }, []);
  
  const saveOptions = () => {
    setStorage('custom_selectors', selectors);
    alert('配置已保存');
  };
  
  return (
    <div className="p-6 max-w-2xl mx-auto">
      <h1 className="text-2xl font-bold mb-6">自动化配置</h1>
      
      <div className="space-y-4">
        <div>
          <label className="block mb-2">标题选择器</label>
          <input
            type="text"
            value={selectors.title}
            onChange={e => setSelectors({...selectors, title: e.target.value})}
            className="w-full p-2 border rounded"
          />
        </div>
        
        <div>
          <label className="block mb-2">价格选择器</label>
          <input
            type="text"
            value={selectors.price}
            onChange={e => setSelectors({...selectors, price: e.target.value})}
            className="w-full p-2 border rounded"
          />
        </div>
        
        <div>
          <label className="block mb-2">描述选择器</label>
          <input
            type="text"
            value={selectors.description}
            onChange={e => setSelectors({...selectors, description: e.target.value})}
            className="w-full p-2 border rounded"
          />
        </div>
        
        <button
          onClick={saveOptions}
          className="bg-blue-500 text-white py-2 px-4 rounded"
        >
          保存配置
        </button>
      </div>
    </div>
  );
};

export default Options;

总结与展望

本文介绍了如何使用Chrome Extension Boilerplate React Vite构建浏览器自动化工具,涵盖了内容脚本开发、跨页面通信、数据存储和用户界面设计等核心技术点。通过这个框架,你可以快速开发出功能强大的浏览器自动化工具,从简单的表单填写到复杂的数据抓取和分析。

项目后续可扩展方向:

  • 集成AI功能实现智能页面分析
  • 添加多语言支持(利用项目内置的i18n模块packages/i18n/
  • 实现云同步功能,共享自动化规则

掌握这些技术后,你可以开发各种实用工具,如网页监控、自动测试、内容聚合等,极大提升工作效率。立即开始探索,释放浏览器自动化的无限可能!

项目完整文档和更多示例,请参考README.md和各模块详细说明。如有问题,可通过项目的Discord社区获取支持。

【免费下载链接】chrome-extension-boilerplate-react-vite Chrome Extension Boilerplate with React + Vite + Typescript 【免费下载链接】chrome-extension-boilerplate-react-vite 项目地址: https://gitcode.com/GitHub_Trending/ch/chrome-extension-boilerplate-react-vite

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐