OpenReplay Spot 浏览器扩展开发与构建指南:从 `yarn dev` 本地调试到 Chrome MV3 打包发布
可观测性开发工具前端后端【免费下载链接】openreplaySession replay, cobrowsing and product analytics you can self-host. Best for reproducing issues and iterating on your product.项目地址https://gitcode.com/gh_mirrors/op/openreplay点击查看免费下载Spot 是 OpenReplay 项目内置的一款浏览器扩展用户直接在浏览器里录制自己发现的 Bug 画面即可自动生成包含网络请求、控制台日志、点击轨迹、Web Vitals 等完整信息的 Bug 报告免去开发与测试之间的反复沟通。本文以 spot/README.md 为主线结合spot/目录下的 WXT 配置、Service Worker、离屏录制模块与后端 Spot 路由实现完整讲解该扩展的本地开发环境搭建、Ingest 接入点切换、源码结构以及如何编译出可手动加载的 Chrome MV3 扩展包。Spot 是什么把发现 Bug变成提交即完成的报告Spot 的核心定位在 spot/README.md 中有明确描述直接在浏览器中录制你所看到的 Bug即时生成包含工程师修复所需全部信息的综合 Bug 报告comprehensive bug reports不再需要来回沟通No more back-and-forth。从实现上看这份全部信息不只是视频本身。在 spot/entrypoints/background.ts 中定义的SpotObj数据结构完整勾勒了报告的内容范围base64data录制的视频数据默认video/webmnetwork网络请求列表SpotNetworkRequest[]logs控制台日志{ level, msg, time }clicks页面点击事件{ time, label }locationsURL 变化与navigation性能时间线fcpTime、visuallyComplete、timeToInteractivevitalsWeb Vitals 指标CLS、FCP、FID、INP、LCP、TTFBcrop视频裁剪区间、startTs、浏览器版本、平台与屏幕分辨率等元数据。也就是说一段几十秒的录制会自动附带请求失败、JS 报错、性能指标等工程师真正需要的上下文。这正是 README 所述无需来回沟通的技术基础。环境准备Node 版本与包管理器按照 spot/README.md 的 Contributing 一节开始开发前需要先准备好 Node.js 环境推荐先安装 nvm 或 n 来管理 Node 版本也可以直接使用node v20.0.0的版本包管理器使用 Yarnspot/package.json中通过packageManager: yarn4.5.3固定了版本Yarn 4.x即 Berry。扩展本身基于WXT版本wxt: 0.20.25构建UI 使用SolidJSsolid-js: ^1.9.15样式采用Tailwind CSS 4与 daisyUI另依赖openreplay/network-proxy用于网络请求的代理捕获。postinstall钩子会执行wxt prepare生成类型与构建所需的辅助文件因此首次安装依赖时请确保网络可以拉取这些包yarn install本地开发yarn dev与 Ingest 接入点切换spot/package.json的 scripts 提供了两条开发命令{ scripts: { dev: wxt, dev:firefox: wxt -b firefox, build: wxt build, build:firefox: wxt build -b firefox, zip: wxt zip, zip:firefox: wxt zip -b firefox, compile: tsc --noEmit, postinstall: wxt prepare } }启动开发实例运行yarn dev会直接拉起一个全新的 Chrome 实例Spot 扩展已预先安装好WXT 的 dev 模式会自动 watch 代码变更并热更新。对应的浏览器启动参数在 spot/wxt.config.ts 中定义webExt: { chromiumArgs: [--user-data-dir./.wxt/chrome-data], },也就是说开发用的浏览器会使用spot/.wxt/chrome-data作为独立的用户数据目录与你的日常浏览器配置隔离。关键一步切换 Ingest 接入点README 明确强调了一个常见陷阱Runningyarn devwill start new chrome instance with spot extension installed already, but you need to change ingest point to your local dev env if you dont have account on app.openreplay.com.即在app.openreplay.com上没有账号时必须把扩展的Ingest Point数据接入点改为你的本地开发环境否则扩展不知道把录制的 Spot 数据提交到哪里。Ingest 的默认值定义在两处均为https://app.openreplay.comspot/entrypoints/background.ts 中的defaultSettings.ingestPointspot/entrypoints/popup/Settings.tsx 中的defaultIngest。修改方式有两种扩展弹窗设置点击扩展图标 → 打开 Settings → 打开 Ingest Point 开关 → 编辑 URL 并 Save。设置页的代码逻辑在 spot/entrypoints/popup/Settings.tsx它用new URL(url)校验合法性isValidUrl通过chrome.runtime.sendMessage({ type: ort:settings, settings: { ingestPoint: val } })写入chrome.storage.local直接在代码中改默认值把defaultSettings.ingestPoint改成你的本地地址如http://localhost:3000适用于本地联调。需要注意background.ts中监听messages.popup.from.updateSettings即ort:settings消息时一旦检测到ingestPoint被修改会立即调用setJWTToken()使当前登录态失效——因为接入点变了旧的登录凭据已不再适用于新后端需要重新登录。Ingest 点在后端对接了什么把 Ingest 指向本地环境后扩展会通过以下 API 与后端通信实现见 ee/api/routers/subs/spot.pyGET {ingest}/spot/v1/ping心跳探活Service Worker 每隔 30 秒调用一次PING_INT 30 * 1000并携带Ext-Version请求头GET {ingest}/api/spot/refreshJWT 刷新接口每 60 秒CHECK_INT 60 * 1000检查并刷新 token返回新的jwt与spotRefreshTokenGET {ingest}/spot/integrations/slack/channels拉取已配置的 Slack 频道列表POST {ingest}/spot/v1/spots创建 Spot 记录返回{ id, mobURL, videoURL }PUT mobURL/PUT videoURL分别上传事件 JSON 与视频二进制POST {ingest}/spot/v1/spots/{id}/uploaded标记上传完成。服务端refresh路由会通过Set-Cookie写入spotRefreshTokenhttponly、securecookie 路径在本地开发时为/spot/refresh生产环境为/api/spot/refresh见 ee/api/routers/subs/spot.py 的LOCAL_DEV判断。登录态由authenticate一并返回的spotJwt、spotRefreshToken、spotRefreshTokenMaxAge驱动见 ee/api/chalicelib/core/users.py。扩展源码结构一览spot/目录采用 WXT 约定的entrypoints/布局各模块职责清晰目录/文件职责spot/entrypoints/background.tsService Worker后台脚本管理 JWT、录制状态机、汇总数据、与后端 API 通信spot/entrypoints/content/Content Script注入录制控制 UI倒计时、录制/暂停/麦克风/结束控制条、保存界面spot/entrypoints/offscreen/离屏文档实际执行tabCapture/getDisplayMedia录制与MediaRecorder编码spot/entrypoints/injected.ts页面主世界MAIN world脚本patchconsole、代理网络请求spot/entrypoints/popup/扩展弹窗登录、开始/停止录制、音频设备选择、设置spot/utils/工具库JWT 过期判断、网络/控制台跟踪、消息常量、base64 转换等消息路由四个角色如何协作各模块通过browser.runtime.sendMessage/tabs.sendMessage通信消息类型集中在 spot/utils/messages.ts按popup、content、injected、offscreen分组。一条典型的录制流程如下用户在 popup 点击开始录制 →popup:start携带area: tab | desktop、mic、audioId、permissions发给 backgroundbackground 向当前活动标签页发送content:mountcontent script 挂载倒计时 UICountdown倒计时结束ort:countend后background 通过chrome.tabCapture.getMediaStreamId获取标签页流或让 offscreen 用getDisplayMedia抓取桌面displaySurface: monitoroffscreen 的ScreenRecorder开始录制每秒产出一个 chunkbackground 把 base64 分片offscr:video-data-chunk转交给 content script 拼装同时 content script 启动点击/位置/Web Vitals 跟踪spot/entrypoints/content/eventTrackers.tsinjected script 采集控制台日志与网络请求ort:bump-logs、ort:bump-network用户点结束 → background 汇总数据 →POST /spot/v1/spots创建记录 → 并行PUT上传事件与视频 → 在新标签页打开${link}/view-spot/{id}查看结果。值得注意的一个细节录制控制条 UI 在桌面录制模式下会跟随当前活动标签页迁移browser.tabs.onActivated监听并会在页面导航完成webNavigation.onCompleted后自动重建保证录制期间切换标签页不会丢控制条实现代码在background.ts的startRecording函数中。离屏录制编码质量与容错spot/entrypoints/offscreen/main.js 中的getRecordingSettings定义了 6 档质量预设对应不同的分辨率与码率档位音频码率 (bps)视频码率 (bps)分辨率4k192000400000004096×21601080p19200080000001920×1080720p默认12800025000001280×720480p960002500000854×480360p960001000000640×360240p64000500000426×240默认初始化使用720precorder.init(getRecordingSettings(720p))。编码上按vp9opus→vp8opus→ 纯video/webm的顺序探测MediaRecorder.isTypeSupported若初始化阶段出现EncodingError编码器初始化失败还会自动降级重试 vp8/vp9提升兼容性。帧率约束为{ min: 20, max: 30 }录制上限3 分钟分片间隔 1 秒mRecorder.start(1000)。视频数据通过消息通道回传时受浏览器消息大小限制因此代码以24MBhardLimit 24 * 1024 * 1024为基准把 Blob 切成 base64 分片convertBlobToBase64Chunks再按序号发送由 content script 按index/total重组。音频方面ScreenRecorder._getStream会把标签页音频与麦克风可选echoCancellation: false通过AudioContext.createMediaStreamDestination()混流麦克风不可用时创建静音占位轨道createPlaceholderAudioTrack确保 MediaRecorder 始终有音频轨道可编码。网络与控制台采集的两种实现spot/entrypoints/popup/Settings.tsx中有一个 Use Debugger 开关对应defaultSettings.useDebugger默认false。这对应两套网络采集方案默认方案通过注入页面主世界的脚本spot/entrypoints/injected.ts spot/utils/proxyNetworkTracking.ts以及 content script 的注入机制injectScript向页面插入injected.js采集 console 与网络事件Debugger 方案开启useDebugger后使用 Chrome DevTools Protocol 的debugger权限做更精确的请求跟踪spot/utils/networkDebuggerTracking.ts这也是wxt.config.ts中声明debugger、webRequest、webNavigation权限的原因。控制台日志通过 patchconsole对象实现spot/utils/consoleTracking.ts并提供__or_revokeSpotPatch撤销钩子停止录制后可还原原始 console。打包构建手动加载 Chrome 扩展spot/README.md 的 Building 一节给出了编译自定义版本的完整步骤yarn build构建产物输出到spot/.output/chrome-mv3目录WXT 默认按浏览器类型组织输出目录。随后打开 Chrome地址栏输入chrome://extensions/打开右上角Developer mode开发者模式开关点击Load unpacked加载已解压的扩展程序选择spot/.output下的chrome-mv3文件夹。加载完成后扩展图标会出现在工具栏登录 OpenReplay 账号或本地 Ingest 对应的后端账号即可开始录制。其他构建命令package.json还提供了面向 Firefox 的构建与打包命令yarn build:firefox # 构建 Firefox 版输出 .output/firefox-mv2 yarn zip # 生成 Chrome 版 zip 包 yarn zip:firefox # 生成 Firefox 版 zip 包 yarn compile # 仅做 TypeScript 类型检查tsc --noEmit扩展的 manifest 由 spot/wxt.config.ts 生成关键权限包括manifest: { name: __MSG_extName__, description: __MSG_extDescription__, default_locale: en, host_permissions: [all_urls], permissions: [ storage, tabCapture, offscreen, unlimitedStorage, webNavigation, webRequest, debugger, ], web_accessible_resources: [{ resources: [injected.js, notifications.js, /content-scripts/content.css], matches: [all_urls], }], }其中tabCapture用于抓取标签页媒体流、offscreen用于创建离屏录制文档、debugger用于精确网络跟踪、unlimitedStorage用于存放较大的录制数据。多语言文案位于 spot/public/_locales/en/messages.json通过__MSG_extName__这类占位符引用。面向自托管用户的配置要点如果你部署的是自托管self-hostOpenReplay 实例需要注意以下几点Ingest Point 必须指向你的实例见上文切换 Ingest 接入点一节否则扩展会把数据提交到公共的app.openreplay.com登录凭据使用独立的 Spot JWT服务端登录接口会额外返回spotJwt/spotRefreshToken扩展通过ort:login-token消息写入chrome.storage.local后台再通过setJWTToken维护内存态与定时刷新查看录制的 URL 规则当 Ingest 主机名为api.openreplay.com时报告页链接指向https://app.openreplay.com/view-spot/{id}否则直接使用你配置的 Ingest 地址下的/view-spot/{id}见background.ts的saveSpotData分支。调试与常见问题yarn dev启动后扩展没有出现确认使用的是新拉起的 Chrome 实例--user-data-dir./.wxt/chrome-data而非日常浏览器WXT 的 dev server 需要保持运行。录制后一直提示 couldnt get active login说明 Ingest 点与你登录的账号后端不一致或在ingestPoint变更后 token 被主动失效setJWTToken()需要重新登录。录制结束但视频为空offscreen 模块在stop-recording时会对空 Blob 做诊断输出console.error(No data recorded, diag)包含 recorder 状态、mimeType 支持矩阵、chunk 数量与轨道信息可据此定位是编码器不支持还是媒体流未就绪。消息过大报错视频数据以 24MB 为上限分片传输若仍超限代码会进一步二分切片convertBlobToBase64Chunks内的 safety 分支。小结从 spot/README.md 出发可以看到OpenReplay Spot 是一个典型的 WXT SolidJS 浏览器扩展工程开发阶段一条yarn dev即可拉起带插件的 Chrome 调试实例重点是按自托管场景切换 Ingest 接入点发布阶段yarn build后通过chrome://extensions的 Load unpacked 加载spot/.output/chrome-mv3即可。其内部则通过 background Service Worker、content script、offscreen 离屏录制与注入脚本四个角色的协作把屏幕录制 网络/控制台/点击/Vitals 上下文 一键上传打包成工程师可直接上手修复的完整 Bug 报告。赞分享可观测性开发工具前端后端【免费下载链接】openreplaySession replay, cobrowsing and product analytics you can self-host. Best for reproducing issues and iterating on your product.项目地址https://gitcode.com/gh_mirrors/op/openreplay点击查看免费下载相关推荐React Scan 浏览器扩展开发指南从环境配置到多浏览器构建打包React Scan 浏览器扩展开发指南从环境配置到多浏览器构建打包 导读 本指南以 packages/extension 下的 React Scanner前端性能剖析Notesnook Web Clipper 本地开发指南从源码构建、加载与调试浏览器剪藏扩展Notesnook Web Clipper 本地开发指南从源码构建、加载与调试浏览器剪藏扩展 本指南以 Notesnook 仓库中的 extensions/w前端移动开发桌面应用应用安全GitDiagram浏览器扩展Chrome插件开发与发布GitDiagram浏览器扩展Chrome插件开发与发布 ? 痛点与解决方案 你是否经常需要在GitHub仓库间切换却苦于无法快速理解复杂的项目架构传统的AI 应用开发者工具前端后端数据可视化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考