qdmp-devtools

Session-only, redacted on-device logs for QDMP miniapps, with an optional Taro Vue panel
1,218
Install
npm install qdmp-devtools
Latest Version:0.5.0
Vue:3
License:MIT
Last Updated:Oct 14, 2026
Links: npm
Maintainer: nathanchenlog

QDMP Devtools

用于 QDMP Taro 4 + Vue 3 小程序的手机调试工具,提供 Console、Network、LocalStorage 和操作记录。调试构建自动注入业务页面,共享本次会话的日志与悬浮入口位置;默认显示收起的入口,点击后展开面板。

本 README 对应 qdmp-devtools@0.5.0 正式包,在 0.4.2 基础上新增可选 AI 连接、HTTPS 真机通道、常显版本号和配置页。不需要安装 Skill。Network 支持复制完整 cURL,保留原始认证、Cookie 和签名;使用边界见 Network。构建验证与手机验收的范围见下方连接说明。

交给 AI 的接入指令

把下面这段话交给能访问 npm、操作终端和修改项目文件的 AI 编程工具即可:

请为当前项目接入公开 npm 包 qdmp-devtools。
先检查项目兼容性;新接入默认选择最新稳定版,下载并读取该精确版本包内 README,按推荐流程完成配置、锁定依赖版本及本地验证。
报告安装版本、修改内容、验证结果和待验收事项。未经明确授权,不上传或发布。

不需要把配置代码或版本号复制到提示词中。用户指定版本时使用指定版本;已有项目未明确要求升级时,先核对并读取已安装版本的包内 README,不擅自升级。不能读取目标版本文档或无法执行验证时,报告具体缺失条件。

推荐接入流程

以下命令在小程序前端目录执行,该目录包含项目的 package.json、Taro 配置和源码。示例使用 pnpm 和 macOS/Linux shell;使用 npm 的项目应沿用 npm 与已有锁文件,命令入口相应使用 npm run / npm exec --。不要混用包管理器或生成第二份锁文件。

1. 检查项目并读取精确版本的包内 README

确认项目使用 QDMP、Taro 4、Vue 3,以及 Taro 的 Vite 构建链。检查已有 DevTool、Taro 插件、App 生命周期、构建和上传脚本;本流程不适用于 React 或任意网页项目。

新接入先解析稳定版本,再下载包读取其中的文档。下载到临时目录不会修改业务项目:

DEVTOOLS_VERSION="$(npm view qdmp-devtools@latest version --registry=https://registry.npmjs.org/)"
DEVTOOLS_README_DIR="$(mktemp -d)"
npm pack "qdmp-devtools@$DEVTOOLS_VERSION" --ignore-scripts --registry=https://registry.npmjs.org/ --pack-destination "$DEVTOOLS_README_DIR"
tar -xzf "$DEVTOOLS_README_DIR/qdmp-devtools-$DEVTOOLS_VERSION.tgz" -C "$DEVTOOLS_README_DIR"
cat "$DEVTOOLS_README_DIR/package/README.md"

用户明确指定版本时,将 DEVTOOLS_VERSION 设为指定版本,不再查询 latest。确认解析值非空且符合用户版本要求后才继续;默认不选 next 或 beta 版本。已有接入先查看依赖、锁文件及 node_modules/qdmp-devtools/package.json,读取已安装包的 README;升级也必须读取准备安装的新版本文档。不要用仓库 main 分支或 npm 网页上的其他版本说明替代它。

2. 精确安装公开包

沿用刚才读取的同一个 DEVTOOLS_VERSION:

pnpm add --save-exact "qdmp-devtools@$DEVTOOLS_VERSION"
# npm 项目的等价命令:npm install --save-exact "qdmp-devtools@$DEVTOOLS_VERSION"

公开包不需要专用 Registry 或安装 Token。不要重新查询一次 latest 后安装不同版本;跨终端执行时重新指定已选定的精确版本。保存 package.json 和对应锁文件。

旧私有包、本地 tgz 或手动宿主迁移时,先确认旧实现的用途,移除被替代的依赖、挂载与重复注入逻辑。其他私有依赖仍需要的 Registry 配置应保留。不要从包内 src、.vue 或未导出的路径导入,也不需要为本包额外配置 manualChunks。

3. 注册项目级自动注入

将下面内容合并到现有 Taro 配置,保留项目的插件、常量、别名和构建设置:

import { defineConfig } from '@tarojs/cli'

export default defineConfig(async () => {
  const devtoolsEnabled = process.env.TARO_APP_ENABLE_DEVTOOLS === '1'
  return {
    plugins: [
      ...(devtoolsEnabled ? ['qdmp-devtools/taro'] : []),
      // 保留已有插件
    ],
    defineConstants: {
      __DEVTOOLS_ENABLED__: JSON.stringify(devtoolsEnabled),
      // 保留已有常量
    },
  }
})

使用 'qdmp-devtools/taro' 字符串形式注册插件。插件按实际注册路由向业务页注入 QdmpDevtoolsHost,宿主负责共享客户端、样式、默认收起入口、Console 和接入 Taro runtime 的 Network 采集;Storage 和操作记录标签也随面板提供。不用逐页编辑、不用另建客户端或手动挂载面板。纯 op-* 跳转页按设计跳过。

页面必须有持续挂载的根 <view>;允许它之前有注释或 <page-meta>。不要将入口包在 scroll-view、条件根节点或带 transform / perspective / filter 的容器中。class 和动态样式的最终布局仍需实际运行验收。

基础接入无需修改 App 生命周期。需要采集首个页面挂载前的日志、未捕获错误或前后台事件时,再按 生命周期配置 合并现有处理,不覆盖业务回调。

4. 添加明确的调试命令

合并以下 scripts;保留原有 dev、build、业务预检和上传流程:

{
  "scripts": {
    "dev:devtools": "TARO_APP_ENABLE_DEVTOOLS=1 taro build --type weapp --no-check --watch",
    "build:devtools": "TARO_APP_ENABLE_DEVTOOLS=1 taro build --type weapp --no-check"
  }
}

示例适用于已有 taro build --type weapp 的项目。已有构建包含必要前后置任务时,复用这些任务并显式传递开关,不用示例覆盖原脚本。普通生产链路应在外层显式设置 TARO_APP_ENABLE_DEVTOOLS=0,防止继承终端残留的调试开关。不要在基础 build 中硬编码 =1;不要为接入工具删除已有正式构建保护。

运行 pnpm dev:devtools 后,在千岛开发者工具中打开 Taro 输出目录预览。若现有项目输出目录不是 dist,后续校验使用项目的实际路径,不猜测目录。

5. 完成本地双构建验收

停止同一输出目录的 watch 进程后执行。下面示例假设普通 build 生成 Taro dist:

pnpm exec qdmp-devtools doctor . --offline
TARO_APP_ENABLE_DEVTOOLS=0 pnpm run build
pnpm exec qdmp-devtools verify-build dist --normal
pnpm run build:devtools
pnpm exec qdmp-devtools verify-build dist

doctor 负责静态诊断,不能单独证明构建隔离。正常产物必须通过 --normal 检查;调试产物必须有页面覆盖报告、业务页宿主、共享入口代码和样式。命令返回 JSON,失败返回非零退出码;处理 error finding 后重新验证。已解释的 warning 可以保留在交付报告中。

若 build 已包含 EMP 编译,应识别项目现有的 Taro 与 EMP 输出和对应报告,再使用正确的模式校验,不能把 EMP 目录当作 Taro 目录验证。

6. 有 QDMP 上传链路时,预检最终 EMP 产物

包内预检命令的前提是:前端有 qdmp.json 且 loader 为 EMP,qdmp CLI 可用,基础 build 可在继承调试开关时生成 Taro weapp 到 dist。符合条件时添加:

{
  "scripts": {
    "upload:devtools": "qdmp-devtools upload"
  }
}

默认验收只执行准备,不上传:

pnpm upload:devtools --prepare-only
# 不添加脚本时:pnpm exec qdmp-devtools upload --prepare-only

该命令让 qdmp build 及其内部构建继承调试开关,生成全新 EMP 产物,并用本次 Taro 注入报告校验。成功返回 ok: true、prepared: true、uploadInvoked: false 和覆盖页数。非标准构建链、输出目录或硬编码关闭开关的脚本不能直接套用;保留生产保护,报告不兼容点,评估项目已有的独立调试编译链路。

成功预检后 dist 是 EMP 上传产物,不等于开发者工具需要的 Taro 预览输入。若要回到本地预览,先保存需要的 EMP 产物,再运行 pnpm build:devtools 恢复 Taro 输出。预检失败会恢复命令执行前的 dist。

接入完成的标准

验收层级 必须提供的证据
依赖与配置 读取、安装版本一致;依赖精确锁定;项目条件匹配;配置与脚本改动可检查。
普通构建 普通构建成功,产物 verify-build --normal 通过,不包含 DevTool 标记。
调试 Taro 构建 调试构建成功,verify-build 通过;预期业务页覆盖,跳过页有说明。
EMP 最终产物 有适用链路时完成 --prepare-only 或等价独立编译校验;报告明确未上传。
开发者工具与手机 分别检查默认入口、跨页位置、拖动、收起重开、短长列表滚动及复制;没执行就标为待验收。

本地构建通过可报告“配置与本地构建验证完成”,不能据此报告所有页面真机正常、上传成功或体验版本已启用。

AI 执行约定

  1. 以准备安装的精确版本包内 README为技术依据,先确认前端目录、包管理器、QDMP / Taro / Vue / Vite 和构建输出。不匹配或缺少关键条件时给出已确认事实与最小下一步检查,不猜测实现。
  2. 默认采用本 README 的项目级自动注入路线。不要同时混用旧手动宿主、每页新客户端、私有包与公开包;不要额外添加业务日志、录制标记、过滤规则或缓存初始化。
  3. 保留现有插件、App 生命周期、业务预检、UBT、生产隔离和上传配置。接入工具不需要修改小程序身份、版本号、登录凭据或 qdmp.json 的业务字段。
  4. 正式路径不静态导入 taro-runtime / taro-host / vue,调试专用 runtime 使用构建常量保护。入口 query 只控制已构建工具的显示,不是构建授权或访问鉴权。
  5. 执行对应的本地双构建及适用的 EMP 预检。没有上传授权时只使用 --prepare-only,不上传、启用体验版本、提审或发布。不在接入过程中安装 Skill 或运行本包维护者的发布脚本。
  6. 交付实际读取及安装版本、修改文件、锁文件状态、所执行命令与结果、覆盖/跳过页面、诊断及待完成的开发者工具/手机验收。区分“未执行”“失败”“通过”,不要把命令已调用写成验收成功。

详细配置与功能

基础接入完成后按需阅读下文。Console、Network、LocalStorage、操作记录随自动宿主提供;自建客户端和手动挂载属于进阶替代方式,不是标准接入的必要步骤。

生命周期配置(可选)

自动宿主在页面挂载后开始采集;若需要更早开始或接入 App 错误,可在现有 App 初始化模块中声明受构建常量保护的动态导入:

const devtoolsRuntime = __DEVTOOLS_ENABLED__
  ? import('qdmp-devtools/taro-runtime')
  : null

在项目已有的生命周期内合并对应调用,保留原有业务处理;options / error / event 使用该回调实际参数:

// 现有 onLaunch(options) 内:
void devtoolsRuntime?.then(m => m.configureDevtoolsEntry(options))
// 现有 onError(error) 内:
void devtoolsRuntime?.then(m => m.captureDevtoolsError(error, 'app'))
// 现有 onUnhandledRejection(event) 内:
void devtoolsRuntime?.then(m => m.captureDevtoolsError(event.reason, 'unhandled-rejection'))
// 现有 onShow / onHide 内(按需):
void devtoolsRuntime?.then(m => m.recordDevtoolsLifecycle('foreground'))
void devtoolsRuntime?.then(m => m.recordDevtoolsLifecycle('background'))

不要新建另一份 createDevtools 单例。Vue 渲染错误可合并到现有 app.config.errorHandler;已有处理已写入 console 时避免重复记录。devtools=1 可展开已构建的调试面板,devtools=0 可关闭;这些参数不能让普通包获得调试能力。不要在每次 onShow 中强制开始采集。

开启、收起与关闭

推荐的自动注入接入在调试构建中开始采集并显示收起的入口;普通构建排除工具。仅安装依赖不会自动改写项目配置。

下面的实例 API 适用于已经启用的自动单例或进阶自建客户端;自动单例应从 qdmp-devtools/taro-runtime 取得,按构建常量保护动态导入。

操作 调用方式 行为
默认接入 createDevtools({ network: { runtime: Taro } }) + 挂载面板 自动采集并显示可拖拽悬浮入口
手动控制接入 createDevtools({ autoStart: false }) 初始不采集、不显示入口,调用 start() 后开启
开启并显示入口 devtools.start({ show: false }) 开始 Console 和已接入的 Network 采集,面板保持收起
开启并展开面板 devtools.start({ show: true }) 开始采集并直接展示面板;start() 默认也是此行为
展开面板 devtools.show() 仅对已开启实例生效
收起面板 devtools.hide() 继续采集,保留记录
关闭工具 devtools.stop() 停止两类采集、隐藏面板并清空记录
暂停 Console devtools.setPaused(true) Network 不受影响;传 false 恢复
暂停 Network devtools.network.setPaused(true) 不记录新请求,已有在途记录可补齐结果;传 false 恢复
清空 Console devtools.clear() 只清空 Console,不关闭工具
清空 Network devtools.network.clear() 只清空 Network,不关闭工具

默认接入无需额外调用 enableDebug()。如果使用 autoStart: false,由项目调试开关调用 enableDebug() / disableDebug()。避免每次 onShow 都无条件开启,否则用户关闭工具后,切回前台会再次开启。

切页与面板收起不清空会话。实例销毁后不恢复历史记录;已开启前发生的请求和日志无法补录。

Console 使用

  • 开启后自动采集 console.debug/log/info/warn/error,原 console 的参数和调用保持不变。
  • 默认在序列化、入库前过滤 debug/log/info 中以 [service] receive msg: 开头的 QDMP 通信日志(含拆分参数形式);不会占用日志容量或命中关键词。warn/error 和业务日志保持采集,不修改底层通信本身。
  • “已过滤通信”/导出的 filtered transport 表示排除的噪声数,“已淘汰”/evicted 表示超容量丢失的日志数;两者独立。通信噪声不触发面板刷新,计数在下次真实日志或面板操作时更新,防止渲染引发通信的循环。需要排查原始通信时,可创建实例时设置 filterTransportLogs: false。
  • 点击“收起”后继续收集,通过“日志 N”悬浮入口展开;跨页使用同一单例保留日志。
  • 筛选级别与关键词组合生效;最新日志在上,点击单条展开完整脱敏内容。
  • “暂停采集”会停止记录新日志,但不阻止原 console 输出。“继续采集”恢复。
  • “清空”删除 Console 日志;“关闭调试”停止 Console 和 Network 采集、隐藏面板并清空两类记录。
  • “复制”复制符合条件的日志(按发生时间排序),不是截图;桥接返回成功后才提示已复制。
  • 面板最多渲染最新 150 条;复制包含全部匹配记录。导出超过 200,000 字符会明确提示缩小范围,不静默截断。
  • console 订阅只采集开启之后发生的日志,不能恢复历史日志或原生日志。

Network 使用

打开工具后切换到 Network。推荐接入已对 Taro runtime 开启采集。下方配置只适用于进阶自建客户端;自动 Taro 单例采用内置配置,不提供动态修改规则的接口。不要为了照抄示例另建与自动宿主并存的实例。

下述“复制 cURL”从 0.4.2 正式版开始提供;0.4.1 不包含该入口。

import Taro from '@tarojs/taro'
import { createDevtools } from 'qdmp-devtools'

const devtools = createDevtools({
  network: {
    runtime: Taro,
    maxEntries: 200,
    maxBodyChars: 16000,
    maxBytes: 2000000,
    getPage: () => Taro.getCurrentPages?.().slice(-1)[0]?.route,
    redactKeys: ['yourSensitiveField'],
    // 按接入项目的接口约定识别业务失败;核心不预设业务成功码。
    isBusinessError: body => body?.success === false,
  },
})
// 创建后已默认开始采集;挂载 DevtoolsPanel 即显示悬浮入口。
  • request、uploadFile、downloadFile 每次调用独立记录,返回原始 Task/Promise,保留取消、回调和宿主可用进度。
  • 列表默认只有搜索及全部/异常/等待中;更多状态、类型、方法收在筛选面板,可组合、单项移除及重置。
  • 异常汇总 HTTP 错误、传输失败和已识别业务错误,不包含主动取消。进入详情时隐藏筛选栏,返回后保留条件。
  • 详情包含 URL、页面、时间、耗时、请求与响应头/正文、错误、文件摘要;结构化数据可切换 JSON 树与文本。
  • 每条请求及详情提供“复制 cURL”:复制完整原始 URL、方法、请求头和请求体,包括认证、Cookie、签名等敏感值,不脱敏。只写入本地剪贴板,不执行或发送请求;请勿公开分享。文本/JSON 保留原始内容,GET 参数及表单按编码转换,二进制以 Base64 管道还原;上传保留原始文件路径与表单,电脑执行前需替换为对应文件。
  • 完整 cURL 与脱敏记录隔离,仅在当前会话内存暂存,共用总容量预算,不进入 Console、Network 普通快照/导出或操作报告;清空、关闭、销毁和淘汰记录时释放。正文展示超限不截断 cURL;单条完整命令超过 200,000 字符或剩余预算不足时明确拒绝复制。不能可靠还原的动态 getter、自定义对象或嵌套查询/表单也会报错,不复制残缺命令。原生自动追加但未传入接口的请求头不属于可观测入参,不宣称为线级抓包。
  • 自动复制失败时显示可手动复制的完整 cURL;只有剪贴板确实成功才提示已复制。复制前已淘汰的记录需要重新发起请求,旧记录无法补录原文。
  • Console/Network 暂停与清空独立;关闭工具清空两者。暂停后在途记录仍可完成,清空或关闭后旧回调不能恢复记录。
  • 会话仅保存在内存;实例销毁后无历史恢复。后台保留同一实例仍属于本次会话。
  • 普通记录存储前脱敏,覆盖结构化字段、JSON 字符串、表单、查询参数和登录请求 code;响应业务 code 保留。普通记录不保存二进制或本地完整路径;完整 cURL 是上述显式复制通道的例外。
  • 默认最多 200 条、每字段/正文 16,000 字符、总序列化存储预算 2 MB(UTF-16 估算,非堆内存精确计量)。超限有截断标记及淘汰数量。
  • 支持单条/筛选结果文本复制、JSON 导出。原生外部文件保存要求 getFileSystemManager、env.USER_DATA_PATH、saveFileToDisk,文件管理器需支持 writeFile 和 unlink;完成/失败后尝试清理临时文件,不自动分享。
  • 缺少外部文件保存能力时明确报错且不落盘,不将复制或沙盒内保存当作外部文件导出成功。浏览器适配使用 Blob 下载。

验证边界:此前宿主集成通过了开发者工具中的采集、筛选、组合条件、详情返回与重置检查;Android/iOS 和宿主外部 JSON 文件保存仍需按接入项目验收。仓库测试与打包通过不代表这些能力已完成真机验收。

Storage 面板(0.4.1)

调试构建自动注入的面板增加 Storage 标签,无需业务页面单独挂载或添加存储采集代码。参考千岛开发者工具的 Storage 面板,仅保留 LocalStorage:Key / Value 表格、搜索和固定底部 Add / Refresh / Clear / Hide;点击条目查看详情、复制、编辑或删除。

在 QDMP 原生小程序中,LocalStorage 明确标注为 QDMP 小程序缓存 · 当前 appId,通过传入的 Taro/QDMP runtime 读取,并保留原生数据类型。面板名称用于统一入口,数据来源仍是小程序的原生缓存。

在 Taro H5(runtime.getEnv() === 'WEB' 且存在真实浏览器 Storage / Document)中,读取当前网页实际 localStorage,值保持 string。Clear 只清空当前数据源;Hide 保留采集并收起面板。Cookies / SessionStorage 不在此面板提供。

  • 打开 Storage 时读取,支持按 Key / 已显示的 Value 搜索、手动刷新、查看数据类型与匹配项数,以及复制 Key / Value。
  • 支持单项新增、编辑和删除;字符串直接编辑,数字、布尔值、对象、数组使用 JSON 校验,null 可直接保存。编辑保持原始类型,可主动切换类型;新增同名 Key 时确认覆盖。
  • Token、密码等敏感 Key 和嵌套字段默认隐藏,可查看原值或确认后复制原值。默认复制仍为脱敏值;编辑读取真实值,不把脱敏文本写回缓存。隐藏值不参与 Value 搜索。规则识别无法保证涵盖全部业务敏感字段,分享前请检查。
  • 删除确认 Key;一键清空作用于当前小程序的全部缓存,包括搜索结果之外的项,并提示可能清除登录状态和本地设置。删除和清空不可撤销。
  • 成功后刷新;Bridge 失败、超时或接口缺失时显示错误,不假装操作成功。部分 Key 读取失败时其他项仍可查看。

自定义小程序 Vue 宿主的 runtime 需提供 getStorageInfo、getStorage、setStorage、removeStorage、clearStorage、showModal、setClipboardData,支持 callback / Promise 两种接口。浏览器宿主需令 getEnv() 返回 WEB,使用浏览器存储并提供弹窗及剪贴板接口。自动 Taro 宿主直接使用 Taro runtime。

缓存原文不会主动写入 Console、Network 或操作记录,面板收起/卸载时释放内存副本;不会清除业务缓存。列表预览最多 240 字符,展开最多 20000 字符,复制包含完整值(超过 200000 字符会提示,避免静默截断)。编辑保存按钮位于顶部,便于手机键盘展开时操作。开发者工具与真机的 Storage、键盘和滚动行为仍需分别验收。

操作复现记录(0.4.1)

仅用于显式启用 DevTool 的调试构建;普通正式构建必须剔除工具。跨页保留入口距底部的位置;录制中重新展开自动回到操作记录。

  1. 打开悬浮入口 → 操作记录 → 开始记录,无需填写任何表单。
  2. 使用工具顶部的 收起 后复现问题,录制继续;重新打开面板查看时间线。录制中直接显示 结束记录 和 标记问题,不显示“更多”;标记问题不用输入文字,不结束录制。
  3. 结束记录,事件冻结,不自动复制。面板仍直接显示完整正序时间线,不展示或切换摘要;点击事件可查看原始 JSON。
  4. 复制,输出简短技术概览+元数据+全部已收录时间线,自行粘贴给 AI/工单。问题现象在接收端另行描述,不自动发送。
  5. 结束后主操作仅为 复制 → 复制 JSON → 重新记录,同一行排列,无“更多”、无常驻报告/JSON 文件导出。复制 JSON 输出完整原始结构;重新记录前,未交付时须确认替换。

简短概览仅汇总版本、时长、错误/业务失败、请求/未完成请求、操作/页面变化与过滤/截断计数,不重复每条事件。错误、请求和页面等完整证据保留在时间线中;时间相邻不表示因果,HTTP 200 不表示业务成功。兼容既有 recorder context API,但面板不再采集问题描述。

单次复制保守上限为 60,000 个 JS 字符串长度单位(工具策略,不是系统容量承诺)。操作记录不展示任何文件导出入口;仅超限/复制失败时临时提供 分段复制完整记录,不静默裁剪。

  • 每段最多 12,000 单位,带会话/段号,保留所选 Markdown/JSON 格式,正文可完整拼接。每段先粘贴再复制下一段,收齐后分析。
  • 仅真实整份剪贴板成功或全部分段复制成功才解除面板未交付保护。手动选择不自动确认交付。
  • 原生剪贴板失败后尝试浏览器兼容路径;分段复制仍失败时可在当前分段文本框手动复制,时间线仍保留,不展开一整份报告。
  • 当前千岛开发者工具隐藏 service-host 的一键复制限制仍未解决;本轮不修改宿主,真机复制待验收。
  • 采集只存当前会话内存,重启小程序会丢失;分享前人工检查敏感信息。

采集范围不扩大:可观测的点击、长按、值变更/输入完成(不含输入值)、页面进出、显式接入的前后台、录制期间业务日志、未捕获错误和 Network 摘要。不回填开始前的记录,不包含完整 query、请求头、网络正文或缓存原文;原生弹窗、Canvas 内部操作和未分发到 Taro 的事件可能缺失。

收录上限仍为 JSON UTF-8 1,000,000 字节 / 2,000 条 / 10 分钟,先到先停,不覆盖旧事件。预留结束信息和可编辑说明空间,会略早于 1 MB 停止;摘要及完整报告的文本体积可能大于收录 JSON。规则脱敏不能保证识别所有自由文本,分享前需检查。

需要可靠区分“点了保存”和“保存成功”时,在调试构建分支补充稳定的业务名称及结果,不传用户内容:

// 必须使用项目已有的编译期布尔常量;正式构建取 false 并验证产物剔除。
const runtime = __DEVTOOLS_ENABLED__ ? import('qdmp-devtools/taro-runtime') : null
function record(name: string, result: string) {
  void runtime?.then(m => m.recordDevtoolsAction(name, result)).catch(() => {})
}
// 分别放在实际业务开始、成功或失败的分支内:
record('album.save', 'started')
// await 原有保存逻辑成功后:record('album.save', 'succeeded')
// 原有失败分支:record('album.save', 'failed')

组件可使用静态 data-devtools-action="drawings.open" 标注可观测交互,或 data-devtools-ignore="true" 排除整个区域。不要将输入内容绑定到这些属性。前后台可在 App 的 onShow/onHide 调用同一调试 runtime 的 recordDevtoolsLifecycle('foreground' / 'background')。

核心自建实例支持 createDevtools({ recording: { filterLog: entry => ... } }) 项目级日志过滤;内置系统过滤先执行,未捕获错误不被项目规则静默丢弃。自动 Taro 单例使用内置规则;没有暴露动态修改规则接口。

手动记录和耗时

devtools.info('[export][save]', { stage: 'download:start' })
// 关键业务日志:直接入库,并原样输出到控制台,不依赖 console hook,避免重复采集。
devtools.logToConsole('error', '[export][save]', { stage: 'album:save', code: 42 })
const result = await devtools.trace('保存海报', () => savePoster())
const text = devtools.exportLogs({ level: 'error', query: 'poster' })
const json = devtools.exportLogs({ format: 'json' })
const unsubscribe = devtools.subscribe(state => { /* 自定义面板更新 */ })
unsubscribe()

trace 保留原返回值/异常,记录成功失败及耗时,不自动记录参数和返回体。 手动记录同样遵循开启/暂停开关;logToConsole 在关闭或暂停时仍保留控制台输出,但不入库。 Network 仅观测接入 runtime 的请求、上传和下载,不观测宿主内部网络,不提供远程命令。

进阶:自建客户端与手动挂载

以下示例用于理解包的最小 API 或临时单页调试。完整的新项目不要据此在每个业务页重复挂载, 标准接入使用前文“推荐接入流程”。本节代码同样只能位于显式调试构建中;未使用构建隔离的静态导入会让正式包包含工具。

  1. 创建会话单例 src/debug.js,不要在每个页面重复创建实例。
import Taro from '@tarojs/taro'
import { createDevtools } from 'qdmp-devtools'

export const devtools = createDevtools({
  maxEntries: 300,
  redactKeys: ['userId'],
  network: {
    runtime: Taro,
    redactKeys: ['userId'],
    getPage: () => Taro.getCurrentPages?.().slice(-1)[0]?.route,
  },
})

// 创建实例时已默认开启;以下方法用于关闭后重新开启。
export function enableDebug() { devtools.start({ show: false }) }
export function disableDebug() { devtools.stop() }
  1. 将面板放在每个需要调试的页面根容器中(不要放进 scroll-view 或带 transform 的父节点)。 面板只有开启后才显示;原页面的流程、路由和样式不变。
<template>
  <view class="page">
    <DevtoolsPanel v-if="active" :client="client" :runtime="runtime" />
    <!-- 原有业务内容 -->
  </view>
</template>
<script>
import Taro, { useDidShow, useDidHide } from '@tarojs/taro'
import { ref } from 'vue'
import DevtoolsPanel from 'qdmp-devtools/vue'
import 'qdmp-devtools/style.css'
import { devtools } from '../../debug'
export default {
  components: { DevtoolsPanel },
  setup() {
    const active = ref(true)
    useDidShow(() => { active.value = true })
    useDidHide(() => { active.value = false })
    return { client: devtools, runtime: Taro, active }
  },
}
</script>

network.runtime 提供 request/uploadFile/downloadFile,用于采集网络请求;面板的 runtime 提供剪贴板、窗口尺寸及可用文件能力。QDMP 项目两处均传入经过 taro-plugin-qd 适配的 Taro。 核心也可用于其他框架,自行订阅并渲染 snapshot()。 面板样式由显式的 qdmp-devtools/style.css 导入;不需要添加 manualChunks,也不要从包内路径 导入 src 或 .vue 文件。 页面留栈但不可见时卸载面板,避免隐藏页面也不断渲染;单例日志不会因此清空。 悬浮入口默认位于右下角;传入 badge-position="left" 可移到左下角。 入口支持拖拽到小程序可见范围内,拖动不触发展开;收起面板继续采集。同一 DevTool 会话切页后保留入口位置,关闭调试或结束小程序会话后重置。 默认自动开启;需要项目手动控制时,创建实例可传入 autoStart: false。

  1. 在 App 生命周期接入未捕获错误(合并已有 handler,不覆盖业务处理):
onError(error) { devtools.captureError(error, 'app') },
onUnhandledRejection(event) { devtools.captureError(event.reason, 'unhandled-rejection') },

Vue 的渲染错误可在既有 app.config.errorHandler 中调用 captureError; 如果既有 handler 已经 console.error,无需再记录一次。 自建核心实例的启动时机由接入项目控制;自动 Taro 宿主按生命周期配置节处理 devtools 参数。本包不提供服务端鉴权。

上传带 DevTool 的调试包

上传时注意 QDMP CLI 的二次构建:部分版本的 qdmp build 会执行普通 npm run build。 调试开关必须传递到最后一次构建,并验证 EMP 最终产物;不能仅验证上传前的 Taro 包。 上传成功后还需启用对应体验版本并在真机验收。

本节适用于 0.4.0 及之后包含 upload CLI 的版本;更早的稳定版不支持此命令。

在小程序前端目录的 package.json 中合并以下脚本,保留其他现有脚本:

{
  "scripts": {
    "upload:devtools": "qdmp-devtools upload"
  }
}
# 在包含 package.json 和 qdmp.json 的前端目录执行
pnpm upload:devtools --prepare-only # 完整构建和校验,不上传
pnpm upload:devtools                # 校验通过后调用 qdmp upload
pnpm upload:devtools -- --description "DevTool 真机验收"

前置条件:已按上述方式注册插件和调试开关;当前目录有 EMP qdmp.json; build 使用 taro build --type weapp、输出目录为 dist;qdmp CLI 可用。 运行前停止同目录的 watch 构建,避免同时写入产物。 命令全程设置 TARO_APP_ENABLE_DEVTOOLS=1,执行 qdmp build(其内部执行项目的 build), 构建插件将本次页面注入报告另存到临时目录,避免 EMP 清理中间产物时丢失。 命令据此检查页面覆盖,以及 dist/main 的最终 EMP 页面、入口代码和样式。 构建前备份旧 dist,失败时恢复,避免旧产物被误认为此次构建成功。 验证通过才执行 qdmp upload,认证及上传结果由 QDMP CLI 提示;支持透传 --env、--description。 普通 upload 保持原用途,不自动开启 DevTool。安装依赖不会自动修改宿主的 package.json,需添加上述脚本。 不添加脚本时,也可以直接执行 pnpm exec qdmp-devtools upload --prepare-only 或 pnpm exec qdmp-devtools upload。

仅校验成功时,会输出 ok: true、prepared: true、uploadInvoked: false 和页面数量。 实际上传是否成功,以 QDMP CLI 返回的上传结果及版本号为准。上传后启用对应体验版本,真机确认悬浮入口。

提示或现象 处理方式
找不到 upload:devtools 脚本 在当前前端目录的 package.json 中添加上述 scripts 项。
CLI 仅显示 doctor / verify-build 用法 当前安装版本不包含 upload 命令,需安装包含该功能的版本。
找不到 qdmp 安装并配置项目使用的 QDMP CLI,确认当前终端可执行 qdmp。
DevTool upload blocked 按 findings 检查插件开关、页面注入或 EMP 样式;修复后重新运行,失败时不会进入上传。

排障与可靠性检查

自动注入使用 Vue SFC/模板与脚本解析器,按 src/app.config.ts/js/json 的页面及分包列表识别页面,避免误注入页面目录中的普通组件。支持字面量配置及 defineAppConfig({...});动态生成路由会给出诊断,不会执行项目配置代码。op-* 重定向页仍跳过。

页面首部允许注释和 page-meta,随后必须为持续挂载的根 view。支持自闭合根节点、额外兄弟节点、script setup、Options API 和 defineComponent。条件根节点、scroll-view 根节点、重复/冲突宿主及明确的 inline transform 会被拒绝。动态样式和 class 的最终布局仍需真机检查,静态分析不证明其计算样式安全。

watch 构建默认告警并跳过错误页面;非 watch 构建和 CI 默认严格失败。配置 ['qdmp-devtools/taro', { mode: 'strict' }] 可在 watch 中也启用严格模式。CI 总是严格。构建会产生 qdmp-devtools-report.json,包含页面覆盖与失败诊断。

# 只读检查;不自动升级依赖。--offline 跳过 npm latest 查询。
pnpm exec qdmp-devtools doctor .
# 调试 Taro 产物:路由、页面输出、注入报告、宿主代码及样式
pnpm exec qdmp-devtools verify-build dist
# 常规构建完成后检查 DevTool 标记是否泄漏
pnpm exec qdmp-devtools verify-build dist --normal
# EMP 编译后使用对应 Taro 构建的报告检查最终产物
pnpm exec qdmp-devtools verify-build emp-output --emp --report dist/qdmp-devtools-report.json

命令输出 JSON;失败返回非零退出码。配置开关的静态检查只是提示,必须通过调试/常规双构建确认隔离。EMP 检查需要本次对应的 Taro 报告;不可用历史报告代替本次编译证据。使用默认读取微信格式的 EMP 编译器时,应以 Taro --type weapp 的 WXML/WXSS 为输入;编译进程成功但样式为空不算验收通过。

现象 优先检查
安装后没有入口 安装不会改配置;确认显式开关及字符串插件注册,再查页面报告和实际产物。
部分页面不显示或严格构建失败 检查注册路由、根 view、page-meta 顺序、条件根和诊断;不能把跳过的纯跳转页算成失败。
入口在新页面下移、不可拖动或被盖住 排查重复手动宿主、容器 transform / perspective / filter、裁剪及原生层级;确认使用当前安装包重新编译。
Network 没有请求 只采集开启后接入 Taro runtime 的 request / uploadFile / downloadFile;宿主内部或未经过该 runtime 的请求不可见。
普通包含工具 检查继承的环境开关、无条件插件和静态 runtime/面板导入;重建并运行 --normal 校验。
上传预检失败或手机没有入口 检查 QDMP 二次构建、对应的本次注入报告和 EMP 样式;Taro 成功不等于 EMP 或手机成功。
复制失败 区分宿主剪贴板能力和命令/报告生成;使用面板提供的手动或分段复制兜底,不宣称一键复制已修复。

Console 日志降噪(0.4.0 起)

  • 默认收起 [service] create instance 和 [page] 页面进入日志,点击“显示系统日志”查看。警告、错误和其他业务日志不因来源被隐藏。
  • 系统日志最多保留 30 条,且不超过总容量的三分之一;容量不足时优先淘汰系统日志。
  • 脱敏后的级别、全文相同的错误,在最近一次发生后 5 秒内再次出现会合并,显示次数及首次、最近时间。不同文本或超时后的错误分别保留,不推断 service/app 两条不同日志一定同源。
  • 错误堆栈默认折叠,展开和复制仍保留详情。仅重复计数变化不主动触发面板刷新,避免运行时错误与面板渲染互相触发;展开、切换筛选或重新打开面板时刷新。
  • 面板“复制”遵循系统日志开关。程序调用 select / exportLogs 默认包含系统日志,可传 includeSystem: false 排除;JSON 包含 category、count、time、lastTime。
  • filtered transport 是已过滤的普通通信日志数量;queueMicrotask 缺失属于真实异常,仍展示摘要,本次降噪不代表该异常已修复。

安全、资源与限制

  • 默认最多 300 条、每条 6,000 字符、5 层、每个对象 30 个字段;超限淘汰旧日志并展示数量。
  • 在入库前序列化脱敏,不持有原始业务对象引用。不调用 getter,支持循环引用、Error、BigInt。
  • 默认隐藏 token/secret/password/authorization/cookie/signature 等字段,以及 phone/mobile/email。 字符串中的 URL、本地路径、常见 token/Bearer/JWT、手机号和邮件会脱敏。 redactKeys 可额外指定业务敏感字段;任意自由文本不能保证完全脱敏,分享前必须人工复核。
  • 原来的系统控制台仍收到原始参数;本包脱敏只覆盖面板、内存记录及导出,不代替业务代码的安全日志规范。
  • 采集记录只存在内存,不写 Storage、不自动上传;关闭调试即清空。主动导出的外部文件和系统剪贴板由用户及操作系统管理。
  • 仅启用本机调试不是权限或保密边界。生产开关可按项目需要加白名单/灰度,但不得在前端放密钥。
  • 监听更新按 100 ms 合并,关闭时无 console 采集。避免记录超大对象,恶意 Proxy/自定义控制台不属于可沙箱化输入。
  • 冻结/只读 console 无法自动挂钩时,可用 devtools.info/error 手动记录。
  • 多实例共享同一 console 时,关闭一个实例不会关闭其他实例。卸载不会覆盖后来安装的第三方 console hook。
  • 包含 JavaScript 日志及接入 runtime 的网络请求记录,不包含 Android logcat、iOS 系统日志、系统级抓包或崩溃前持久化。
  • 普通 H5/自动测试不能证明 QDMP 原生剪贴板、键盘及原生层级正常,发版前须真机验收。

真机验收清单

  1. 默认接入后显示悬浮入口并开始采集;autoStart: false 时不显示、不采集。
  2. 入口可拖到可见范围内,拖动不展开面板,点击入口正常展开。
  3. 收起面板,复现业务错误;重新展开能找到对应日志,跨页后仍保留。
  4. 检查 Info/Warn/Error、关键词、暂停/恢复、清空、展开长日志。
  5. 复制后粘贴核对内容;权限/能力失败时不显示复制成功。
  6. 关闭调试后入口消失且数据清空,重新开启没有之前的日志。
  7. Android/iOS 都测试弹层滚动、搜索键盘和业务弹层叠加;原生组件可能有独立层级限制。

开发验证

npm test 使用 Node 内置测试,npm run test:package 会先构建 ESM/CJS 核心与 Vue adapter,再验证编译产物的入口。

# 在源码目录执行
npm ci
npm run test:package
npm pack --dry-run

需要 Node.js 18 或更高版本。Vue 面板以已编译 JavaScript 交付,仍应由接入方的 Taro/Vue 项目构建验证。 本仓库仅包含通用包,不包含业务登录配置、真机日志或业务应用。 自动测试不能替代 Android/iOS 原生能力验收。公开 npm 发布由维护者单独执行。

连接开发者 AI(0.5.0)

此包内置手机端连接器,配套独立服务 qdmp-devtools-mcp 提供标准 MCP 接口;不依赖千岛开发者工具自带的 MCP,也不需要 Skill。HTTPS 手机通道需要 MCP 0.1.0-beta.3 或后续兼容版本。MCP 的部署与版本状态以其包内 README 为准。

  1. 前端按本 README 启用调试构建;普通构建继续排除 DevTool。
  2. 在电脑安装配套 MCP 服务,按它的 README 将 qdmp-devtools-mcp --project /absolute/path/to/frontend --tls-cert /path/server.crt --tls-key /path/server.key 配置成 AI 的 stdio MCP 服务。使用绝对 Node 和 CLI 路径,Node >=22.12.0。
  3. 让 AI 调用 connection_info,复制返回的完整 connectionString。打开小程序 DevTool → 配置 → 连接 AI(MCP),粘贴并点击连接。连接串 5 分钟过期、只能使用一次,不写入源码、配置或日志。
  4. AI 先调用 list_sessions 确认项目、设备、页面、SDK 版本和构建标识,再使用明确的 sessionId 读取数据。点击“断开”或“关闭调试”停止连接;关闭/收起面板不停止连接。

支持读取 Console、Network、原生缓存,以及开始/标记/结束操作记录和分页读取记录。仅按需传输脱敏快照;不提供任意代码执行、请求重放、缓存写入或原始 cURL。缓存名称仍可能包含业务信息,只连接可信电脑。配对后 AI 可读取这些数据并控制录制,数据会进入所选 AI 服务的处理范围。普通日志脱敏不能保证识别任意自由文本中的敏感信息。

默认仅监听电脑回环地址,适用于同机模拟器。手机默认使用 qd.request 的 HTTPS 通道(SDK 0.5.0-beta.4 / MCP 0.1.0-beta.3 起),无需原生 WebSocket;模拟器默认 WebSocket,显式选择 transport: "websocket" 可保留 WSS。MCP 服务需配置运行端信任、地址匹配的 TLS 证书,不要关闭证书校验。手机在同一可信局域网时,需要 MCP 显式加 --host <电脑局域网 IPv4>,再调用 connection_info 的 mode: "device";手机不能使用 127.0.0.1。原生 SocketTask、局域网权限、TLS 和 App 前后台行为必须分别在 Android/iOS 真机验收,模拟器通过不代表真机通过。当前没有公网中继或自动打洞。

读取结果是有时间戳的采集快照,不等于全部系统请求。分页游标 60 秒过期;网络/二进制/超长内容沿用采集器截断限制。控制命令必须等待返回执行结果,超时代表状态未知;查询状态后用同一 requestId 重试,避免重复操作。

iPhone 真机连接验证范围

已在测试项目体验版的 iPhone 15 Pro 上通过 HTTPS 配对,使用 AI 客户端读取日志、网络请求与原生缓存键,并完成 probe 往返验证。手机应保持前台;跨页连接、后台恢复、长期稳定性及 Android 仍需在目标项目单独验收。当前本机模式需要同一可互通局域网、匹配地址的证书,以及 iPhone 对签发 CA 的完全信任。

Related Packages

@tarojs/plugin-framework-vue3

Vue3 框架插件

106,098 37,728
taro-plugin-pinia

Taro&vue3 支持使用 Pinia 进行状态管理的插件

3,934 10
@vuepress/plugin-debug

VuePress plugin - debug

3,854 2,833
vue-json-debug

Vue Json Debug plugin

1,603 4
nuxt-ssr-api-logger

Nuxt module for logging SSR API requests.

22,791 11

Version History

Version Released License
0.5.0 MIT
0.4.2 MIT
0.4.1 MIT
0.4.0 MIT
0.3.6 MIT