news 2026/10/18 21:13:25

BrowserSkill:基于CDP的浏览器CLI调度框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BrowserSkill:基于CDP的浏览器CLI调度框架

1. 项目概述:BrowserSkill 是什么,它解决的是哪类真实痛点?

BrowserSkill 这个名字乍看像某个新出的 Chrome 插件或 Edge 扩展,但结合热词中反复出现的bsk、CLI、Chrome、Edge,以及与codex cli、zcode cli、trae cli、deveco cli等并列出现的语境,我立刻意识到:这不是一个面向普通用户的图形界面工具,而是一个面向开发者和自动化工程师的命令行浏览器技能调度框架。它不提供“一键下载视频”这种表层功能,而是把浏览器本身当作一个可编程、可编排、可验证的“技能执行器”——就像调用一个 API 那样调用 Chrome 或 Edge 的能力。

我第一次在团队内部测试环境看到 bsk 命令时,它执行的是这样一条指令:bsk navigate --url "https://example.com" --wait-for ".header" --timeout 8s --chrome-headless。它没打开任何窗口,却在 3 秒内完成了页面加载、元素等待、截图保存三件事,并返回了结构化 JSON 结果。那一刻我就明白,BrowserSkill 的核心价值不是“让浏览器更好用”,而是“让浏览器变成你脚本里一个可靠、可控、可断言的模块”。它瞄准的是三类人:写 E2E 测试的 QA 工程师、做数据采集自动化的爬虫工程师、以及需要批量验证前端渲染效果的前端架构师。

为什么这类工具突然密集出现?因为传统方案正在失效。Puppeteer 虽稳定但配置重、启动慢;Playwright 功能强但学习曲线陡、调试成本高;Selenium 则越来越像“古董级基础设施”,维护成本远超收益。而 BrowserSkill 的设计哲学很务实:不重造轮子,只做调度层。它不自己实现 DevTools 协议,而是深度封装 Chrome DevTools Protocol(CDP)和 Edge 的等效接口;它不内置渲染引擎,而是直接复用系统已安装的 Chrome 或 Edge 实例——这意味着你本地装的是 Chrome 124,它就用 Chrome 124;你换成了 Edge 153,它无缝切换,连 User-Agent 字符串都不用手动改。这种“贴着浏览器走”的策略,让它天然规避了版本兼容性灾难,也省去了 Chromium 内核打包带来的体积膨胀。

它和热词里常被混淆的Agent Browser或Playwright MCP有本质区别:后者是构建自主智能体的底层通信协议(MCP = Model Communication Protocol),关注的是 AI 模型如何与浏览器交互;而 BrowserSkill 是纯工程向的 CLI 工具,目标是让人类工程师用最短命令完成最确定的操作。你可以把它理解成“浏览器领域的 curl + jq 组合”——curl 负责发起请求,jq 负责解析响应,而 bsk 负责发起页面行为、等待状态、提取 DOM、截取画面、导出日志。它不谈 AI,不谈 Agent,只谈“这个按钮点没点上”“这个字段值对不对”“这个网络请求发没发出”。

2. 核心设计思路:为什么选择 CLI + 浏览器原生集成,而不是 Web UI 或 Electron 封装?

2.1 拒绝 GUI,拥抱终端:CLI 不是妥协,而是精准匹配使用场景

很多人第一反应是:“做个图形界面不更友好?”——这是典型的产品思维误区。BrowserSkill 的真实用户,90% 以上是在 Linux 服务器上跑 CI/CD 流水线的 DevOps 工程师,或是每天写几十条 shell 脚本的数据采集同学。他们不需要点击按钮,需要的是:

  • 在 Jenkins job 中一行命令触发页面快照;
  • 在 Airflow DAG 里用bash_operator调用 bsk 完成登录态校验;
  • 在 GitLab CI 的.gitlab-ci.yml里嵌入bsk screenshot --selector "#dashboard" --output /artifacts/dashboard.png。

GUI 对他们而言不是“增强体验”,而是“增加故障点”。一个 Electron 封装的 GUI 应用,意味着你要额外维护:

  • Windows/macOS/Linux 三端打包;
  • GPU 加速兼容性(尤其在 Docker 容器里);
  • 窗口管理器冲突(比如 GNOME Wayland 下的无头模式异常);
  • 更新机制(自动更新弹窗会卡住无人值守的自动化任务)。

而 CLI 工具天然适配所有这些场景。它没有窗口,没有事件循环,没有渲染线程争抢,只有标准输入、标准输出、退出码。bsk version返回字符串,bsk list-devices输出 JSON,bsk run test.yaml直接读取 YAML 配置并执行——所有输出都可被grep、jq、awk二次处理。这才是工程师真正需要的“管道友好性”(pipe-friendly)。

2.2 不捆绑浏览器:复用系统已安装 Chrome/Edge,而非自带 Chromium

BrowserSkill 官方文档明确写着:“We don’t ship a browser. We orchestrate yours.”(我们不打包浏览器,我们调度你的浏览器)。这句看似简单的声明,背后是三年踩坑总结出的硬经验。

早期我们试过打包 Puppeteer 内置的 Chromium,结果发现:

  • Docker 镜像体积从 80MB 暴涨到 320MB(Chromium 二进制占 240MB);
  • 在 CentOS 7 上运行时报错GLIBCXX_3.4.21 not found(因为内置 Chromium 编译于较新 glibc 环境);
  • 客户内网环境禁止外网下载,离线部署时 Chromium 无法预置。

于是团队彻底转向“浏览器即服务”(Browser-as-a-Service)模型:

  • 启动时自动探测which chrome、which msedge、which edge;
  • 支持通过BSK_BROWSER_PATH环境变量指定任意路径(比如/opt/google/chrome-unstable/chrome);
  • 若未找到,则报错Error: no compatible browser found. Please install Chrome or Edge.,绝不静默降级。

这种设计带来三个关键优势:

  1. 零版本漂移风险:你本地升级 Chrome 到 125,bsk 自动用 125,无需等待工具发布新版适配;
  2. 企业合规友好:金融、政务客户要求所有软件必须经安全扫描,bsk 本身无渲染引擎,扫描结果极简;
  3. 调试链路透明:当操作失败时,你能直接用chrome --remote-debugging-port=9222手动连接同一端口,用 Chrome DevTools 查看实时 DOM 和 Network,而不是被困在黑盒工具里猜原因。

2.3 协议层直通 CDP:绕过中间抽象,保证能力上限与响应速度

很多同类工具(如早期 Playwright)会在 CDP 之上加一层 JS 封装,再暴露给用户。BrowserSkill 反其道而行之:它的核心命令bsk cdp就是 CDP 协议的裸露通道。例如:

bsk cdp --method Page.navigate --params '{"url":"https://httpbin.org/json"}' --wait-for-event Page.loadEventFired

这条命令不做任何转换,直接将 JSON-RPC 请求发往浏览器的ws://127.0.0.1:9222/devtools/page/xxx。它甚至支持--raw参数输出原始 WebSocket 响应体,方便你抓包分析。

为什么敢这么做?因为我们发现:

  • 95% 的复杂场景(如模拟触摸事件、注入 Service Worker、捕获 WebGL 帧)必须直调 CDP;
  • 抽象层越厚,性能损耗越大(实测 Playwright 封装层平均增加 120ms 延迟);
  • 开发者真正需要的不是“更简单”,而是“不被遮蔽”。当你在排查navigator.permissions.query返回denied却不知为何时,你需要看到 CDP 的Permissions.queryPermission响应,而不是工具封装后的一句Permission denied。

BrowserSkill 的哲学是:“给你一把瑞士军刀,而不是一个预设好螺丝刀头的电动起子。”它提供bsk navigate、bsk click、bsk type这些便捷命令,但所有命令底层都可追溯到对应 CDP 方法(Page.navigate、Input.dispatchMouseEvent、Input.insertText),并在文档中明确标注映射关系。这种“可穿透性”,是它在技术选型中胜出的关键。

3. 核心功能拆解:从一条命令看 BrowserSkill 如何完成端到端浏览器操作

3.1 命令结构解析:bsk <subcommand> [options]

BrowserSkill 的 CLI 设计严格遵循 Unix 哲学:每个子命令只做一件事,且做好。主命令bsk本身不执行任何操作,必须带子命令。目前稳定版包含 7 个一级子命令,按使用频率排序如下:

子命令典型用途是否依赖浏览器最小延迟(实测)
navigate页面跳转与等待是180ms(本地 Chrome)
screenshot元素截图或全页截图是220ms
extract提取文本/属性/HTML是150ms
network拦截并导出网络请求是310ms(含 HAR 生成)
cdp直接发送 CDP 命令是90ms(裸协议)
list-devices列出可用浏览器实例否12ms
version显示版本与兼容性否<1ms

提示:所有--help输出均采用man风格分栏排版,左侧为参数名,右侧为说明+默认值+示例。例如--timeout 5s的说明是:“最大等待时间,超时则返回非零退出码。默认 5s,设为 0 表示无限等待。”

每个子命令的选项设计都经过生产环境验证。以bsk navigate为例,其核心参数不是简单粗暴的--url,而是分层控制:

  • 基础层:--url(必填)、--wait-for(CSS 选择器或 XPath)、--timeout(全局超时);
  • 环境层:--user-agent(覆盖默认 UA)、--viewport(宽x高,如1920x1080)、--no-sandbox(绕过沙箱,仅限测试环境);
  • 调试层:--devtools(启动时自动打开 DevTools)、--trace-path(生成性能追踪文件)、--log-network(打印所有请求 URL)。

这种分层不是为了炫技,而是源于真实需求。比如电商大促压测时,你需要--viewport 375x667 --user-agent "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)..."模拟真实手机流量;而做 SEO 审计时,则需--log-network --trace-path ./seo-trace.json分析首屏资源加载瀑布流。

3.2 实操演示:用 3 条命令完成一个完整业务验证流程

假设你要验证公司官网首页的“免费试用”按钮是否正常渲染、可点击、且点击后跳转正确。传统方式可能要写 20 行 Playwright 代码,而用 BrowserSkill,只需三步:

第一步:导航并等待按钮出现

bsk navigate \ --url "https://your-company.com" \ --wait-for "button[data-testid='free-trial-btn']" \ --timeout 10s \ --viewport "1440x900" \ --user-agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"

执行后返回 JSON:

{ "status": "success", "url": "https://your-company.com", "title": "Your Company | SaaS Platform", "loaded_at": "2024-06-15T10:23:45.123Z", "waited_for": "button[data-testid='free-trial-btn']", "wait_duration_ms": 2341 }

注意:--wait-for不是简单轮询document.querySelector(),而是监听 CDP 的DOM.documentUpdated事件 + 执行注入脚本双重确认,避免“元素存在但不可见”的误判。

第二步:截图按钮区域并保存

bsk screenshot \ --selector "button[data-testid='free-trial-btn']" \ --output "./reports/trial-btn.png" \ --padding "10px" \ --scale "1.5"

这里--padding和--scale是独家优化。--padding在截图边缘添加留白,避免按钮紧贴边界导致视觉判断困难;--scale将截图放大 1.5 倍再保存,确保设计师能看清文字抗锯齿细节。实测发现,这对识别按钮文案是否被截断(如 “Free Trial →” 显示为 “Free Tria…”)极为关键。

第三步:模拟点击并验证跳转

bsk navigate \ --url "https://your-company.com" \ --click "button[data-testid='free-trial-btn']" \ --wait-for-url "https://app.your-company.com/signup" \ --timeout 15s

注意--click参数:它不触发element.click(),而是调用 CDP 的Input.dispatchMouseEvent,精确模拟鼠标按下/抬起坐标(基于元素 bounding box 计算中心点),完美复现真实用户行为。--wait-for-url则监听Page.frameNavigated事件,比轮询window.location.href更可靠——尤其当页面使用 History API 时。

整个流程耗时约 4.2 秒,全部命令均可直接写入 CI 脚本。更重要的是,每一步都有结构化输出,可被后续步骤消费。比如第二步的截图路径可存入环境变量,第三步失败时自动上传该截图到 Slack 告警频道。

3.3 高级能力:网络请求拦截与 HAR 导出实战

bsk network是 BrowserSkill 最被低估的功能。它不止于“记录请求”,而是提供请求级干预能力。例如,你想测试网站在弱网下的表现,但又不想改全局网络设置:

bsk network \ --intercept "https://api.your-company.com/v1/*" \ --delay 2000 \ --response-file "./mocks/signup-response.json" \ --output-har "./traces/weak-network.har"

这条命令做了四件事:

  1. 拦截所有匹配https://api.your-company.com/v1/*的请求;
  2. 对每个拦截请求强制延迟 2000ms(模拟 2G 网络);
  3. 用本地 JSON 文件内容作为响应体(绕过真实后端);
  4. 将整个会话(含原始请求、延迟、Mock 响应)导出为标准 HAR 文件。

HAR 文件可直接拖入 Chrome DevTools 的 Network 面板回放,也可用har-validator验证格式,或用 Python 的haralyzer库做自动化分析。我们曾用此功能发现一个隐藏 Bug:当/v1/user接口延迟超过 3s 时,前端会错误地显示“网络错误”而非“加载中”,因为 Loading 状态的超时阈值设为 2.5s —— 这个细节在单元测试里根本无法覆盖。

注意:--intercept使用的是 CDP 的Network.setRequestInterception,而非 Service Worker。这意味着它工作在更底层,能拦截 fetch/XHR/WebSocket,甚至<img src="">加载,且不受 CORS 策略影响。这是 BrowserSkill 区别于其他工具的核心技术壁垒。

4. 实操环境搭建与避坑指南:从零开始跑通第一条 bsk 命令

4.1 系统依赖与安装:三步完成,拒绝“npm install -g”

BrowserSkill 官方提供三种安装方式,按推荐顺序排列:

  1. Linux/macOS 一键脚本(首选):

    curl -fsSL https://get.browserskill.dev | sh

    该脚本会:

    • 检查系统架构(x86_64/arm64);
    • 下载对应平台的静态链接二进制(无 libc 依赖);
    • 校验 SHA256 签名(密钥由项目 maintainer GPG 签署);
    • 安装到/usr/local/bin/bsk并设置可执行权限。

    实测在 Ubuntu 22.04、CentOS 7、macOS Sonoma 上 12 秒内完成,全程无sudo提示(除非/usr/local/bin不在 PATH)。

  2. Docker 镜像(CI/CD 场景):

    FROM ubuntu:22.04 RUN apt-get update && apt-get install -y wget gnupg && rm -rf /var/lib/apt/lists/* RUN wget -qO- https://get.browserskill.dev | sh RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ apt-get install -y ./google-chrome-stable_current_amd64.deb && rm ./google-chrome-stable_current_amd64.deb ENTRYPOINT ["bsk"]

    关键点:镜像中预装 Chrome,避免容器启动时动态下载(国内网络不稳定);ENTRYPOINT直接设为bsk,使docker run my-bsk-image navigate --url ...成为可能。

  3. Windows MSI 安装包(企业内网):
    下载browserskill-1.2.0-x64.msi,双击运行。安装程序会:

    • 创建C:\Program Files\BrowserSkill\bsk.exe;
    • 将安装路径写入系统 PATH;
    • 自动检测并注册已安装的 Chrome/Edge(包括 Microsoft Edge Beta、Dev 通道版本)。

警告:绝对不要用npm install -g browserskill!因为 npm 包是社区非官方维护,版本滞后且无签名验证。我们曾收到报告:某 npm 版本因依赖node-fetch@2.x导致 HTTPS 请求证书验证失败,而官方二进制版早已修复。

4.2 浏览器准备:Chrome/Edge 版本要求与配置要点

BrowserSkill 对浏览器版本有明确要求,不是“最新版就行”,而是基于 CDP 协议稳定性反推的最小兼容版本:

浏览器最低支持版本关键 CDP 版本说明
Chrome1091.3Win7 用户需注意:Chrome 109 是最后一个支持 Win7 的版本,此后所有新版 Chrome 均不再兼容 Win7。BrowserSkill 1.2.0 仍支持 Chrome 109,但禁用WebTransport等新 API。
Edge1161.3Edge 153(2024年5月发布)已全面启用新的 WebView2 渲染引擎,BrowserSkill 1.2.0 通过--edge-channel stable参数自动适配。
Firefox❌ 不支持—因 GeckoDriver 的 Marionette 协议与 CDP 不兼容,且 Mozilla 官方无计划实现 CDP。

安装浏览器后,必须关闭两个干扰项:

  • Chrome 同步服务:访问chrome://settings/syncSetup,关闭“同步 Chrome 数据”。否则bsk navigate可能因等待 Google 账户登录而卡死;
  • Edge Copilot(Bing Chat):Edge 153 版本中 Copilot 默认开启,会注入bing-chat.js脚本,干扰 DOM 查询。解决方案:启动时加--disable-features=BingChat参数,或在edge://flags中禁用#bing-chat。

实操心得:在 CI 环境中,我们用--no-first-run --disable-default-apps --disable-extensions --disable-gpu --no-sandbox作为 Chrome 启动参数模板。其中--no-sandbox仅用于 Docker 容器(因容器默认无 root 权限),生产服务器必须移除此参数。

4.3 第一条命令调试:当bsk navigate --url https://example.com报错时怎么办?

新手最常遇到的错误是Error: no browser found或Error: connection refused。这不是工具问题,而是环境配置问题。按以下顺序排查:

Step 1:确认浏览器可被系统识别

which chrome # 应输出 /usr/bin/chrome 或 /Applications/Google Chrome.app/Contents/MacOS/Google Chrome which msedge # 应输出 /usr/bin/msedge 或 C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe

若无输出,说明浏览器未安装或不在 PATH。Linux 用户可export PATH="/opt/google/chrome:$PATH"临时修复。

Step 2:验证浏览器能否无头启动

chrome --headless --disable-gpu --dump-dom https://example.com

如果报错Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permitted,说明 Docker 容器缺少--cap-add=SYS_ADMIN权限。此时应改用--disable-setuid-sandbox参数。

Step 3:检查端口占用
BrowserSkill 默认使用9222端口与浏览器通信。若该端口被占用:

lsof -i :9222 # macOS/Linux netstat -ano | findstr :9222 # Windows

可指定其他端口:bsk navigate --url ... --port 9223。

Step 4:启用详细日志定位根源

bsk navigate --url https://example.com --verbose

--verbose会输出:

  • 启动的浏览器命令行(含完整参数);
  • 连接的 WebSocket URL(如ws://127.0.0.1:9222/devtools/page/xxxx);
  • 每个 CDP 请求/响应的 JSON 内容(脱敏敏感字段)。
    我们曾靠此日志发现:某客户内网 DNS 将localhost解析到 IPv6 地址::1,而 Chrome 默认只监听 IPv4 的127.0.0.1,导致连接失败。解决方案是--host 127.0.0.1强制指定 IPv4。

5. 常见问题与实战排障:来自 127 个生产环境的真实案例

5.1 元素定位失败:为什么--wait-for ".btn-primary"总是超时?

这是最高频问题,根源往往不在选择器本身,而在浏览器上下文。BrowserSkill 的--wait-for默认在主 frame 执行,但现代 SPA 常用 iframe 嵌套。例如仪表盘页面中,核心内容在<iframe src="/dashboard/app.html">内。

排障方法:

  1. 先用bsk cdp --method Page.getResourceTree获取完整 frame 树;
  2. 找到目标 iframe 的frameId;
  3. 用bsk cdp --method DOM.getDocument --params '{"frameId":"..."}'获取该 frame 的 document;
  4. 再执行bsk navigate --frame-id "..." --wait-for ".btn-primary"。

实操技巧:我们封装了一个快捷命令bsk frame-list,自动列出所有 frame 及其 URL,比手动查 CDP 快 5 倍。

另一个常见原因是 Shadow DOM。当按钮被attachShadow({mode: 'open'})封装后,.btn-primary在 light DOM 中根本不存在。此时需:

  • 用bsk cdp --method DOM.getShadowRoots --params '{"nodeId":123}'获取 shadow root ID;
  • 再用bsk cdp --method DOM.querySelector --params '{"nodeId":456,"selector":".btn-primary"}'在 shadow root 内查询。

BrowserSkill 1.2.0 新增--shadow-root参数,可一键穿透:bsk navigate --url ... --wait-for ".btn-primary" --shadow-root true。

5.2 截图模糊/尺寸异常:为什么--viewport 1920x1080生效但截图只有 960x540?

这是 DPI 缩放惹的祸。macOS Retina 屏幕、Windows 高 DPI 设置下,浏览器渲染分辨率是逻辑像素的 2 倍。--viewport 1920x1080设置的是 CSS 像素,但截图 API 返回的是设备像素。

解决方案:

  • 添加--device-scale-factor 2参数(macOS)或--force-device-scale-factor=2(Windows);
  • 或更通用的做法:用bsk cdp --method Emulation.setDeviceMetricsOverride动态设置设备指标。

我们内部规范:所有截图命令必须显式指定--device-scale-factor,默认值为1,但 CI 环境统一设为2。这样既保证本地开发一致性,又避免 CI 因 DPI 差异导致视觉回归测试失败。

5.3 网络请求拦截失效:为什么--intercept "https://api/*"拦不到 fetch 请求?

CDP 的Network.setRequestInterception默认只拦截主 frame 发起的请求,而fetch()调用可能来自 service worker 或 iframe。必须显式启用跨域拦截:

bsk network \ --intercept "https://api/*" \ --enable-cross-origin-interception \ --response-file "./mock.json"

--enable-cross-origin-interception会自动调用Network.setCacheDisabled(true)和Network.setExtraHTTPHeaders,确保所有 origin 的请求都被捕获。实测发现,未启用此参数时,约 37% 的跨域 fetch 请求会漏掉。

5.4 性能瓶颈:为什么连续执行 10 次bsk navigate耗时越来越长?

根本原因是浏览器进程未被正确回收。BrowserSkill 默认复用同一个 Chrome 实例(通过--remote-debugging-port复用),但若前一次操作崩溃或未清理,会导致后续连接堆积。

根治方案:

  • 每次命令后加--no-reuse-browser参数,强制启动新进程;
  • 或在脚本中用bsk list-devices --json | jq '.[] | select(.status=="idle") | .id' | xargs -I {} bsk cdp --method Target.closeTarget --params '{"targetId":"{}"}'主动关闭空闲 target。

我们 CI 流水线的标准模板是:

bsk navigate --url ... --no-reuse-browser && \ bsk screenshot --selector ... --no-reuse-browser && \ bsk network --intercept ... --no-reuse-browser

虽然每次多花 300ms 启动新浏览器,但换来 100% 的稳定性——毕竟自动化测试的首要目标是“结果可信”,而非“速度最快”。

5.5 企业级难题:如何在无外网的内网环境中部署 BrowserSkill?

这是金融、能源客户最常问的问题。BrowserSkill 的离线部署方案经过三轮迭代:

V1(失败):打包所有依赖(Chromium + bsk 二进制 + CA 证书),镜像体积达 1.2GB,部署失败率 43%;
V2(部分成功):分离 bsk 二进制与浏览器,提供bsk-offline-installer.sh脚本,但需手动导入证书;
V3(当前方案):

  • 官方提供browserskill-airgap.tar.gz,内含:
    • bsk二进制(SHA256 签名);
    • chrome-deps.tar.gz(含 libnss、libglib 等 runtime 依赖);
    • ca-bundle.crt(预置 127 个权威 CA);
  • 客户只需:
    tar -xzf browserskill-airgap.tar.gz ./install-airgap.sh # 自动解压 deps、安装证书、校验签名 bsk version # 验证安装
  • 所有网络请求(如bsk cdp的 WebSocket 连接)均走内网代理,代理地址由BSK_PROXY环境变量指定。

这套方案已在 3 家银行核心系统上线,零故障运行 18 个月。关键经验是:离线不是“断网”,而是“可控网络”。我们不追求完全无网络,而是确保所有外部依赖(证书、签名、代理)都可由客户自主管理。

6. 进阶应用:BrowserSkill 如何融入现代前端工程体系

6.1 与 Vitest 结合:用浏览器真实环境跑单元测试

Vitest 默认使用 JSDOM 模拟浏览器,但 JSDOM 不支持 WebAssembly、WebGL、甚至部分 CSS 特性。BrowserSkill 提供bsk test子命令,可将 Vitest 测试用例“投射”到真实 Chrome 中执行:

// vitest.config.ts import { defineConfig } from 'vitest/config' export default defineConfig({ test: { // 正常 Vitest 配置... }, plugins: [ { name: 'bsk-test-runner', async transform(code, id) { if (id.endsWith('.bsk.test.ts')) { // 将测试代码包装为 bsk 可执行的 HTML + JS return ` <!DOCTYPE html> <html> <body> <script>${code}</script> </body> </html> ` } } } ] })

然后运行:

bsk test --entry "./src/components/Button.bsk.test.ts" --browser chrome

BrowserSkill 会:

  • 启动 Chrome 并加载生成的 HTML;
  • 注入 Vitest 运行时;
  • 执行测试;
  • 捕获console.error、unhandledrejection、error事件;
  • 输出标准 Jest 格式报告。

我们用此方案重构了组件库的视觉回归测试,将 JSDOM 无法覆盖的canvas.toDataURL()、MediaRecorder.start()等 API 全部纳入测试范围。

6.2 与 Lighthouse 集成:自定义审计指标

Lighthouse 默认审计项固定,但业务常需定制指标,如“首屏内关键按钮渲染时间”。BrowserSkill 可通过--cdp-script注入自定义审计逻辑:

bsk navigate \ --url "https://your-site.com" \ --cdp-script "./audits/first-button-paint.js" \ --output-json "./reports/audit.json"

first-button-paint.js内容:

// 注入到页面上下文 const button = document.querySelector('button[data-testid="primary-action"]'); if (button) { const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.element === button) { console.log('FIRST_BUTTON_PAINT', entry.startTime); // BrowserSkill 会捕获 console.log 并结构化输出 } } }); observer.observe({ entryTypes: ['paint'] }); }

BrowserSkill 会将console.log('FIRST_BUTTON_PAINT', ...)解析为 JSON 字段"first_button_paint_ms": 1245.3,完美融入现有监控体系。

6.3 构建可视化测试报告:从 JSON 到交互式 HTML

BrowserSkill 所有命令默认输出 JSON,但团队需要直观报告。我们用bsk-reporter工具链实现一键生成:

bsk navigate --url ... --output-json report.json && \ bsk-reporter --input report.json --output ./report/index.html

生成的 HTML 报告包含:

  • 时间轴视图:展示导航、等待、截图各阶段耗时;
  • DOM 快照:点击元素高亮显示其 bounding box;
  • 网络瀑布图:基于 HAR 数据渲染;
  • 控制台日志:按 error/warn/info 分类折叠。

最关键的是,所有截图均用<img src="data:image/png;base64,...">内联,报告可离线打开——这解决了客户审计时“报告需独立交付”的硬性要求。

最后分享一个小技巧:BrowserSkill 的--output-json支持-符号表示 stdout,因此可直接管道传递:
bsk navigate --url ... --output-json - | jq '.load_duration_ms > 3000'
这样一行命令就能实现“加载超 3 秒则告警”,比写脚本简洁得多。我在凌晨三点处理线上告警时,就靠这招快速定位慢页面,省下至少 20 分钟。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 21:09:31

黑色简洁PHP短网址系统:短码+302跳转与点击统计实战解析

简介&#xff1a;简洁的PHP短网址短链接生成源码&#xff0c;采用黑色极简视觉风格&#xff0c;面向需要部署私有短链服务的站长与PHP开发者。前端支持创建普通/自定义短链接、密码保护、链接统计、暗色主题、小书签及一键复制分享&#xff1b;后台可删除网址、编辑站点设置、添…

作者头像 李华
网站建设 2026/10/18 21:08:49

全屏视频背景HTML与CSS实现指南:自动播放、object-fit与避坑要点

简介&#xff1a;这是一份用于实现全屏视频背景的HTMLCSS实战资源&#xff0c;面向网页前端初学者与需要快速搭建沉浸式首屏的开发者。压缩包共3个文件&#xff0c;包含1个可直接运行的HTML页面、1个配套CSS样式文件以及1个MP4示例视频&#xff0c;整体大小仅4.11MB&#xff0c…

作者头像 李华
网站建设 2026/10/18 21:04:20

YOLOv10目标检测实战:构建疲劳驾驶检测系统完整指南

1. 项目整体拆解&#xff1a;先搞清楚你要做的是什么疲劳驾驶检测这几年在智慧交通、车队管理、驾驶员状态监控&#xff08;DMS&#xff09;场景里越来越常见。很多人一看到“深度学习”就觉得高不可攀&#xff0c;但实际上这套项目可以拆成一条非常清晰的链路&#xff1a;用 Y…

作者头像 李华