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

背景

封装了一些浏览器插件自动化中常用的组件,都在 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)
})

小结

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

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

相关推荐
前端小巷子3 分钟前
CSS单位完全指南
前端·css
SunTecTec44 分钟前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink
拉不动的猪2 小时前
前端常见数组分析
前端·javascript·面试
小吕学编程2 小时前
ES练习册
java·前端·elasticsearch
Asthenia04122 小时前
Netty编解码器详解与实战
前端
袁煦丞2 小时前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
一个专注写代码的程序媛3 小时前
vue组件间通信
前端·javascript·vue.js
一笑code3 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员4 小时前
layui时间范围
前端·javascript·layui
NoneCoder4 小时前
HTML响应式网页设计与跨平台适配
前端·html