开发浏览器插件-基于配置自动化执行

背景

封装了一些浏览器插件自动化中常用的组件,都在 Github - chrome-extension-tools 仓库里。

我是基于 vitesse-lite 模板进行二次封装: demo,有兴趣的朋友可以下载跑一下。

以下内容是基于你了解浏览器插件相关的概念,如果是第一次尝试,可以看下 官网文档

使用场景

  1. 自动化执行网页操作
  2. 获取网页应用的数据

功能点

  1. 消息通信:简化 Background、Content Script 和 Side Panel 之间的消息传递
  2. 工作流自动化:实现复杂业务流程的自动化,支持多层级任务定义、循环和重新执行功能
  3. 请求捕获:获取页面的请求
  4. 日志模块:统一日志定义,方便后续的拓展
  5. 类型支持:完整的 TypeScript 类型定义

如何使用

消息通信

目前有很多相关的封装,但这块消息通信的复杂度并不高,为了方便和更适配我的写法,所以我自己重新封装了消息通信的功能。

封装 Chrome Extension 的消息方法,统一 Background, Content Script 和 Side Panel 的消息通信:

  1. Background(Service) -> sv
  2. Content Script -> cs
  3. popup/Side Panel(后面称 Side Panel) -> sp

每个浏览器插件,只会各有一个 Background 和 Side Panel,会有多个 Content Script,所以关于 Content Script 的通信,都需要带上对应的 tabId,保证 Background(Side Panel) 可以给指定的 Content Script 发消息。

Background 发给 Content Script

Background 发给 Content Script 需要带上 tabId 才能指定发给谁:

typescript 复制代码
import { sendMsgByBG, CetDestination } from 'chrome-extension-tools'
const res = await sendMsgByBG('test1', { ... }, { tabId: tabId, destination: CetDestination.cs })

Background 发给 side panel

typescript 复制代码
import { sendMsgByBG, CetDestination } from 'chrome-extension-tools'
const res = await sendMsgByBG('test1', { ... }, { destination: CetDestination.sp })

具体使用,请看消息通信文档

工作流使用

工作流模块是为实现复杂业务流程自动化设计的核心组件,以 Side Panel 为核心,通知 Content Script 或 Background 来执行相关动作。

初始化

Background:

typescript 复制代码
import { initBGMsgListener, initBackground } from 'chrome-extension-tools'
// 初始化消息通知
initBGMsgListener()
// 初始化基本的消息事件
initBackground()

Content Script:

typescript 复制代码
// 入口文件
import { initCSMsgListener } from 'chrome-extension-tools'
initCSMsgListener()

// 指定文件初始化,如果只有一个任务的,可以在入口文件初始化
import { initContentScriptTask } from 'chrome-extension-tools'
// 你的工作流配置
import { getTasks } from '~/tasks/index.task'
// 监听 window message 事件,将接口拦截后的数据发送给 bg 和 cs
initContentScriptRequest()
// 初始化工作流
initContentScriptTask(getTasks())

Side Panel:

typescript 复制代码
import { CetActuator, CetDestination, EVENTS, onMsgInSP, sendMsgBySP } from 'chrome-extension-tools'
// 自定义 logger 对象
import { getTasks, logger } from '~/tasks/index.task'
// 监听接口事件,获取 Content Script 捕获的接口数据
onMsgInSP(EVENTS.CS2SP_GET_REQUEST, async (data) => {
  console.log('data', data)
  return true
})
// 获取当前 Tab 数据
async function getTab() {
  const { data } = await sendMsgBySP<undefined, chrome.tabs.Tab>(EVENTS.SP2BG_GET_CURRENT_TAB, undefined, { destination: CetDestination.BG })
  return data
}
// 执行工作流任务
async function start() {
  logger.info('开始执行')
  // 初始化工作流对象
  const ins = new CetActuator(getTasks(), {
    // 每次执行任务前,工作流模块会执行 getTabId 事件,返回 tabId
    // @ts-ignore
    getTabId: async () => {
      const tab = await getTab()
      return tab ? tab.id : undefined
    },
    taskBeforeCb: (task) => {
      logger.info(`${task.name} 开始执行`)
    },
    taskAfterCb: (task, result) => {
      logger.info(`${task.name} 执行结束 ${result ? '成功' : '失败'}`)
    },
  })
  // 执行工作流
  const result = await ins.run()
  console.log(result)
  logger.info('全流程结束')
}

配置任务

typescript 复制代码
import type { CetWorkFlowConfigure } from 'chrome-extension-tools'
import {
  CetDestination,
  loopCheck,
  sendMsgBySP,
} from 'chrome-extension-tools'
import { EVENT_OPEN_URL_SP2BG } from '~/constants'

export enum TaskNames {
  open = '打开网页',
}

export function getTasks(): CetWorkFlowConfigure[] {
  return [
    {
      name: TaskNames.open,
      spBeforeFn: async () => {
        // 通知 background 打开百度页面
        sendMsgBySP(EVENT_OPEN_URL_SP2BG, { url: 'https://www.baidu.com' }, { destination: CetDestination.BG })
        return {
          next: true,
        }
      },
    },
  ]
}

具体使用,请看文档

接口捕获

接口拦截的配置有点长,具体可以看文档

按文档配置后,当 Content Script 注入了脚本并刷新了一次页面,组件就会捕获到接口并将数据发送给 Background 和 Side Panel,你只需监听对应的事件即可:

typescript 复制代码
import { EVENTS, handleResponseData } from 'chrome-extension-tools'

// Content Script 收到请求后,会通知给 sp
onMsgInSP(EVENTS.CS2SP_GET_REQUEST, async (data) => {
  if (!data)
    return
  const res = {
    url: data.url || '',
    response: handleResponseData(data?.response),
    data: handleResponseData(data?.data),
    body: handleResponseData(data?.body),
    headers: handleResponseData(data?.headers),
    id: data.id,
  }
  console.log(res)
})

小结

上面所提供的核心模块,可以帮助你实现许多的自动化需求,消息通信来将各个模块串联起来,工作流帮你稳定、有序地执行业务步骤、接口拦截可以帮你获取想要的数据。

后续我会提供更多的一些例子,帮助大家能快速上手。

相关推荐
jianzhi0015 分钟前
深入理解 HTML5 Web Workers:提升网页性能的关键技术解析
前端·html·html5
最新资讯动态14 分钟前
掌握DevEco Studio模拟器这些“隐藏功能”,让鸿蒙应用调试效率事半功倍
前端
irises33 分钟前
tabby-vscode代码补全的一些阅读笔记
前端·javascript
2501_9068014833 分钟前
BY组态-低代码web可视化组件
前端·物联网·低代码·数学建模·编辑器·web
hang_bro36 分钟前
element-plus e-tabs与pinia 一起使用的问题
前端·vue.js
VitStratUp37 分钟前
antdvue+tree+transfer+vue3 实现树形带搜索穿梭框
前端·vue.js
千野竹之卫38 分钟前
2025最新云渲染网渲100渲染农场使用方法,渲染100邀请码1a12
开发语言·前端·javascript·数码相机·3d·3dsmax
前端提桶人40 分钟前
Win11 安装 Sentry 监控
linux·前端
南茗啊40 分钟前
echarts地图轮播markpoint-自用记录📝
前端·echarts
__不想说话__1 小时前
面试官问我React Router原理,我掏出了平底锅…
前端·javascript·react.js