{"_id":"@arms/rum-browser-vue","_rev":"2-7b2a14aabfb7f99b62d3184591036d59","name":"@arms/rum-browser-vue","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@arms/rum-browser-vue","version":"0.1.0","keywords":["rum","real-user-monitoring","arms","vue","vue2","vue3","vue-router","error-tracking","monitoring"],"author":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"license":"ISC","_id":"@arms/rum-browser-vue@0.1.0","maintainers":[{"name":"fengsir","email":"fengsir@live.com"},{"name":"yunjin4","email":"xiashujin.xsj@alibaba-inc.com"},{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},{"name":"yangling1996","email":"yl260087@alibaba-inc.com"},{"name":"yunyi-alibaba","email":"ly403664@alibaba-inc.com"},{"name":"alibaba_rum_harmony","email":"yanglanxin.ylx@alibaba-inc.com"}],"dist":{"shasum":"2238d0a465202c48a72cd6a75c08298af98c23ee","tarball":"https://registry.npmjs.org/@arms/rum-browser-vue/-/rum-browser-vue-0.1.0.tgz","fileCount":67,"integrity":"sha512-yPNc7IS6poVkw6m1HRmu2Om8fIt20wOPtjuXbo+cyGDMpHwSnaLEePw+NSOqpwT4IHLVn5lFRP2bX3CrDuV1Bw==","signatures":[{"sig":"MEUCIQCyazscf6gSGRNfX6OX0mlnUCuA6QtXUcnl4M+NO7C9fwIgdrt25kOcEmeTM37XLkEtrz8caIAUMzzkOk+dy6yE1hk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":84954},"main":"lib/index.js","types":"es/index.d.ts","module":"es/index.js","exports":{".":{"types":"./es/index.d.ts","import":"./es/index.js","default":"./es/index.js","require":"./lib/index.js"},"./vue2":{"types":"./es/entries/vue2.d.ts","import":"./es/entries/vue2.js","default":"./es/entries/vue2.js","require":"./lib/entries/vue2.js"},"./vue3":{"types":"./es/entries/vue3.d.ts","import":"./es/entries/vue3.js","default":"./es/entries/vue3.js","require":"./lib/entries/vue3.js"},"./package.json":"./package.json"},"gitHead":"351f1e2c9b645a6dd89655dc6e514eb351bd38a3","scripts":{"build":"build-scripts build --skip-demo","prepublishOnly":"npm run build"},"_npmUser":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"_npmVersion":"10.9.8","description":"Vue plugin for @arms/rum-browser SDK (Vue 2/3 error capture + vue-router view tracking + useRum)","directories":{},"sideEffects":false,"_nodeVersion":"22.22.3","browserslist":["last 2 Chrome versions","last 2 Safari versions","last 2 Firefox versions","last 2 Edge versions","iOS >= 14","Android >= 8"],"dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^4.9.4"},"peerDependencies":{"vue":"2 || 3","vue-router":"3 || 4","@arms/rum-core":">=0.1.11","@arms/rum-browser":">=0.1.16"},"peerDependenciesMeta":{"vue-router":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/rum-browser-vue_0.1.0_1787552781363_0.5651126270272446","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@arms/rum-browser-vue","version":"0.1.1","description":"Vue plugin for @arms/rum-browser SDK (Vue 2/3 error capture + vue-router view tracking + useRum)","author":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"license":"ISC","main":"lib/index.js","module":"es/index.js","types":"es/index.d.ts","exports":{".":{"types":"./es/index.d.ts","import":"./es/index.js","require":"./lib/index.js","default":"./es/index.js"},"./vue2":{"types":"./es/entries/vue2.d.ts","import":"./es/entries/vue2.js","require":"./lib/entries/vue2.js","default":"./es/entries/vue2.js"},"./vue3":{"types":"./es/entries/vue3.d.ts","import":"./es/entries/vue3.js","require":"./lib/entries/vue3.js","default":"./es/entries/vue3.js"},"./package.json":"./package.json"},"keywords":["rum","real-user-monitoring","arms","vue","vue2","vue3","vue-router","error-tracking","monitoring"],"sideEffects":false,"publishConfig":{"access":"public"},"scripts":{"build":"build-scripts build --skip-demo","prepublishOnly":"npm run build"},"dependencies":{},"peerDependencies":{"@arms/rum-core":">=0.1.11","@arms/rum-browser":">=0.1.16","vue":"2 || 3","vue-router":"3 || 4"},"peerDependenciesMeta":{"vue-router":{"optional":true}},"devDependencies":{"typescript":"^4.9.4"},"browserslist":["last 2 Chrome versions","last 2 Safari versions","last 2 Firefox versions","last 2 Edge versions","iOS >= 14","Android >= 8"],"_id":"@arms/rum-browser-vue@0.1.1","gitHead":"d2671fb3a7873af8eb63833c55d152cac061fa01","_nodeVersion":"22.22.3","_npmVersion":"10.9.8","dist":{"integrity":"sha512-Hrf712+9Xa6dSSiT7M4cWzjVpB096lTT0wSMS6uvWf6oNY+LYlF45MiMydXN/L3EBWF7cPikvjfELPUWvjSA8w==","shasum":"937e374b739cf61ef9d5b313323058cfc8308fda","tarball":"https://registry.npmjs.org/@arms/rum-browser-vue/-/rum-browser-vue-0.1.1.tgz","fileCount":67,"unpackedSize":84554,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDqwGzRnpsFYNXOoctB2edNJgkEFDjYBJH9ZQZw1tP8xwIhAI+UmVHdMc+3yQJgzjRfO3Sz6Zf/g8lJrLq62tDY9+8W"}]},"_npmUser":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"fengsir","email":"fengsir@live.com"},{"name":"yunjin4","email":"xiashujin.xsj@alibaba-inc.com"},{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},{"name":"yangling1996","email":"yl260087@alibaba-inc.com"},{"name":"yunyi-alibaba","email":"ly403664@alibaba-inc.com"},{"name":"alibaba_rum_harmony","email":"yanglanxin.ylx@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rum-browser-vue_0.1.1_1788269417385_0.20742533104513616"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-24T06:26:21.180Z","modified":"2026-09-01T13:30:17.961Z","0.1.0":"2026-08-24T06:26:21.500Z","0.1.1":"2026-09-01T13:30:17.529Z"},"author":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"license":"ISC","keywords":["rum","real-user-monitoring","arms","vue","vue2","vue3","vue-router","error-tracking","monitoring"],"description":"Vue plugin for @arms/rum-browser SDK (Vue 2/3 error capture + vue-router view tracking + useRum)","maintainers":[{"name":"fengsir","email":"fengsir@live.com"},{"name":"yunjin4","email":"xiashujin.xsj@alibaba-inc.com"},{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},{"name":"yangling1996","email":"yl260087@alibaba-inc.com"},{"name":"yunyi-alibaba","email":"ly403664@alibaba-inc.com"},{"name":"alibaba_rum_harmony","email":"yanglanxin.ylx@alibaba-inc.com"}],"readme":"# @arms/rum-browser-vue\n\nVue 插件 for `@arms/rum-browser` RUM SDK —— 同时支持 **Vue 2.x + Vue 3.x**（vue-router v3 / v4）。\n\n能力范围：\n\n- **Vue 异常捕获**：接管 `errorHandler`（链式保留原 handler），自动上报 `source: 'vue'` 的异常事件（含 `snapshots` JSON 快照，内部携带 `component_stack` / `component_name` / `lifecycle_hook` / `handling`）\n- **路由视图追踪**：传入 `router` 实例后，经 `router.afterEach` 驱动 `Shell.startView`（手动 view 模式），view.name 收敛为路由模板（如 `/user/:id`），popstate / 首屏 / 懒加载时序问题根治\n- **useRum / $rum**：Vue 3 提供 `useRum()` Composition hook，两端均提供 `this.$rum` 与 `getRum()` 单例\n\n> 不含组件性能监控（列入后续演进）。\n\n## 安装\n\n本插件不独立工作 —— 需与主包 `@arms/rum-browser`（必需 peer dependency）同时安装，并完成主包初始化（见「Vue 3 接入 / Vue 2 接入」）：\n\n```bash\nnpm install @arms/rum-browser @arms/rum-browser-vue\n```\n\n版本可用性：上游依赖 `@arms/rum-core@0.1.11` 与 `@arms/rum-browser@0.1.16` 均已在 npm registry 发布，本包 peerDependencies 下限与 registry 实际产物对齐，外部安装可正常解析（版本约束与发布顺序说明见下文「发布前置条件」）。\n\n## 发布前置条件\n\n发布顺序（严格按序，前一步发版在 registry 生效后，再发布下一步）：\n\n1. **`@arms/rum-core@>=0.1.11`**：含 `Shell.startView` 与 `IConfiguration.trackViewsManually` 能力的发版\n2. **`@arms/rum-browser@>=0.1.16`**：含 PvCollector 手动模式防护（`trackViewsManually` 早退，避免双发 PV）的发版\n3. **`@arms/rum-browser-vue`**（本包）\n\n上游发版状态（peer 下限已与 registry 对齐）：\n\n- **`@arms/rum-core@0.1.11` 与 `@arms/rum-browser@0.1.16` 已在 npm registry 发布**，本包 peerDependencies（`@arms/rum-core >=0.1.11`、`@arms/rum-browser >=0.1.16`）可正常解析，外部项目 `npm install @arms/rum-browser-vue` 不再出现早期的 ERESOLVE 失败（该下限曾为有意占位：安装失败优于运行期缺 `Shell.startView` 能力而损坏，现已解除）\n- 后续版本迭代仍需遵循上述发布顺序（依赖包发版在 registry 生效后，再发布本包），保证 peer 下限始终对应 registry 上具备所需能力的真实产物\n- 仓库内开发期经 workspace 直链源码使用（无需等待发版），安装依赖请遵循仓库惯例使用 `yarn` 或 `scripts/bootstrap.sh`\n\n## 版本要求\n\n| 依赖                | 版本要求   | 说明                                                                                                                   |\n| ------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `@arms/rum-core`    | `>=0.1.11` | 含 `Shell.startView` 与 `IConfiguration.trackViewsManually` 的发版（已发布；发布顺序与下限校准见上方「发布前置条件」） |\n| `@arms/rum-browser` | `>=0.1.16` | 含 PvCollector 手动模式防护（`trackViewsManually` 早退）的发版（已发布）                                               |\n| `vue`               | `2 \\|\\| 3` | —                                                                                                                      |\n| `vue-router`        | `3 \\|\\| 4` | optional，不接入路由时可省略（此时仅启用异常捕获与 `$rum`，view 仍由 SDK 自动采集）                                    |\n\n开发期在 monorepo 内通过 workspace 直链源码使用，无需等待发版。\n\n## Vue 3 接入\n\n```ts\n// main.ts\nimport { createApp } from 'vue';\nimport { createRouter, createWebHistory } from 'vue-router';\nimport ArmsRum from '@arms/rum-browser';\nimport { ArmsRumVue } from '@arms/rum-browser-vue/vue3';\nimport App from './App.vue';\nimport { routes } from './router';\n\nvar app = createApp(App);\nvar router = createRouter({ history: createWebHistory(), routes: routes });\n\nArmsRum.init({\n  endpoint: 'https://your-endpoint',\n});\n// 插件接入不再依赖 init 完成，可在 init 前后任意时序同步调用\napp.use(ArmsRumVue, { rum: ArmsRum, router: router });\napp.mount('#app');\n```\n\n> **时序说明**：插件接入（`Vue.use(ArmsRumVue, ...)`）不再依赖主包 init 完成，可在 init 前后任意时序同步调用；init 与插件接入的先后顺序可互换，两者等价安全。路由首次导航会被内部 pending 机制暂存、init 完成后补发（`loading_type: 'initial_load'`），首屏不丢失。**注意**：init 完成前触发的错误与自定义事件不会被采集（默认配置下 init 几乎瞬间完成；但 Vue2 等同步渲染框架的首屏渲染期错误可能落入此窗口）。若需捕获首屏渲染期错误，可将应用挂载（mount）置于 init 完成后（仅 mount 时序保留 `.then`/`await`，插件接入不再需要）。\n\n### useRum（Composition API）\n\n```vue\n<script setup lang=\"ts\">\nimport { useRum } from '@arms/rum-browser-vue/vue3';\n\nvar rum = useRum();\n\nfunction onCheckout() {\n  try {\n    submitOrder();\n    rum.sendCustom({ type: 'biz', name: 'checkout_click', value: 1 });\n  } catch (e) {\n    rum.addVueError(e);\n  }\n}\n</script>\n\n<template>\n  <button @click=\"onCheckout\">结算</button>\n</template>\n```\n\nOptions API 组件可直接使用 `this.$rum`（install 时自动挂载到 `app.config.globalProperties`）。\n\n## Vue 2 接入\n\n```ts\n// main.ts\nimport Vue from 'vue';\nimport VueRouter from 'vue-router';\nimport ArmsRum from '@arms/rum-browser';\nimport { ArmsRumVue } from '@arms/rum-browser-vue/vue2';\n\nVue.use(VueRouter);\nvar router = new VueRouter({ routes: routes });\n\nArmsRum.init({\n  endpoint: 'https://your-endpoint',\n});\n// 插件接入不再依赖 init 完成，可在 init 前后任意时序同步调用\nVue.use(ArmsRumVue, { rum: ArmsRum, router: router });\nnew Vue({\n  router: router,\n  render: function (h) {\n    return h(App);\n  },\n}).$mount('#app');\n```\n\nVue 2 无 Composition API，不提供 `useRum`：组件内使用 `this.$rum`（install 时自动挂载到 `Vue.prototype`），或从入口导入单例：\n\n```ts\nimport { getRum } from '@arms/rum-browser-vue/vue2';\n\ngetRum().sendCustom({ type: 'biz', name: 'checkout_click', value: 1 });\n```\n\n## 路由追踪说明\n\n> **警告：传入 `router` 后 view/PV 完全由 `afterEach` 驱动，主包自动 PV 被禁用**\n>\n> 插件在 `vueCollector.setup` 中注入 `trackViewsManually: true`：主包 PvCollector 跳过首屏 PV 与 history 拦截（避免双发），view 的创建、命名、计时**完全依赖** `router.afterEach` 驱动（内部调用 `shell.startView`）。这意味着 view 上报以传入的 router 实例真实承载应用导航为前提 —— 若传入的 router 从未完成导航（如仅创建未挂载到应用），view 将不会上报（无报错、无告警）。\n>\n> 不传 `router` 则不注入手动 view 模式，主包 PvCollector 保留自动 PV（URL path 命名），仅启用异常捕获与 `$rum` 能力 —— 无路由追踪诉求时请勿传入 `router`。\n\n传入 `router` 后，插件内部：\n\n1. 在 `vueCollector.setup` 中注入 `trackViewsManually: true`（禁用 PvCollector 自动 PV，避免双发）\n2. 挂载 `router.afterEach`，导航成功后调用 `shell.startView(viewName, { url, loading_type })`\n3. view.name 按 `to.matched` 末段路由模板计算（嵌套拼接），动态段 `:param` 原样保留；catch-all（v4 `/:pathMatch(.*)*`、v3 `*`）展开为实际访问路径\n4. 导航失败（v4 afterEach 第三参 `failure`）与 query-only 变化不计为新视图；同路径重复导航由 `Shell.startView` 同名去重\n5. `loading_type`：ctx 已有 view 时为 `route_change`，否则 `initial_load`\n\n```ts\n// 访问 /user/123 时上报的 view 事件：\n// { event_type: 'view', type: 'pv', name: '/user/:id', loading_type: 'initial_load', ... }\n```\n\n不传 `router` 时不会注入手动 view 模式，view 仍由 SDK 自动采集（URL path 命名）。\n\n## 异常捕获说明\n\ninstall 时接管 `errorHandler` 并链式保留原 handler：先经 `addVueError` 上报，再调用你已有的 handler（未设置时保持 Vue 默认的 `console.error` 可见性，不会吞错）。\n\n上报字段：\n\n```ts\n{\n  event_type: 'exception',\n  type: 'error',\n  source: 'vue',\n  name: 'TypeError',            // error.name（非 Error 值自动 normalize）\n  message: \"Cannot read properties of undefined\",\n  stack: '...',\n  // 扩展信息收敛为单一 JSON 字符串字段（值为 undefined 的内部键不会出现）\n  snapshots: JSON.stringify({\n    component_stack: 'at <OrderList>\\nat <UserPage>',  // 当前组件在前，沿父链向上\n    component_name: 'OrderList',\n    lifecycle_hook: 'hook:mounted',  // Vue errorHandler 的 info 参数\n    handling: 'handled',\n  }),\n  times: 1,\n}\n```\n\n也可在自定义 errorHandler 中手动上报（插件已接管时无需重复调用）：\n\n```ts\nimport { addVueError } from '@arms/rum-browser-vue';\n\napp.config.errorHandler = function (err, instance, info) {\n  addVueError(err, { lifecycle_hook: info });\n};\n```\n\n## API\n\n### 主入口 `@arms/rum-browser-vue`\n\n| 导出                                                     | 说明                                                                              |\n| -------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| `addVueError(error: unknown, context?: VueErrorContext)` | 手动上报 Vue 异常（`component_stack` / `component_name` / `lifecycle_hook` 可选） |\n| `getRum(): VueRumApi`                                    | RUM API 单例（`addVueError` / `sendCustom` / `sendEvent` / `getConfig`）          |\n\n### 子入口 `@arms/rum-browser-vue/vue3`\n\n在主入口基础上增加：\n\n| 导出                  | 说明                                                |\n| --------------------- | --------------------------------------------------- |\n| `ArmsRumVue`          | Vue 3 插件：`app.use(ArmsRumVue, { rum, router? })` |\n| `useRum(): VueRumApi` | Composition hook，返回与 `this.$rum` 相同的单例     |\n\n### 子入口 `@arms/rum-browser-vue/vue2`\n\n在主入口基础上增加：\n\n| 导出         | 说明                                                                         |\n| ------------ | ---------------------------------------------------------------------------- |\n| `ArmsRumVue` | Vue 2 插件：`Vue.use(ArmsRumVue, { rum, router? })`，组件内 `this.$rum` 可用 |\n\n### `VuePluginOptions`\n\n`app.use(ArmsRumVue, options)` / `Vue.use(ArmsRumVue, options)` 的第二参数（源 `src/types/index.ts`）：\n\n| 字段     | 类型        | 必填 | 说明                                                                                                                                                                                                                  |\n| -------- | ----------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `rum`    | `Shell`     | 是   | 主 SDK 实例（`@arms/rum-browser` 默认导出的 `armsRum`，或任意 Shell 子类实例）。可在 `armsRum.init()` 前后任意时序同步传入；反向时序经 pending 队列兜底同样安全                                                       |\n| `router` | `AnyRouter` | 否   | vue-router 实例（v3 `VueRouter` / v4 `Router` 均可，仅依赖 `afterEach` 最小接口）。传入后启用路由视图追踪（注入手动 view 模式，经 `afterEach` 驱动 `startView`）；不传则仅启用异常捕获与 `$rum`，view 由 SDK 自动采集 |\n\n### `getRum()`\n\n返回 `VueRumApi` 单例，包含 `addVueError` / `sendCustom` / `sendEvent` / `getConfig` 四个方法。Vue 3 的 `useRum()`、组件内 `this.$rum`（Vue 3 挂载于 `app.config.globalProperties`、Vue 2 挂载于 `Vue.prototype`）与 `getRum()` 返回**同一实例** —— API 本身无状态，仅持有模块级 shell 引用，插件未初始化时各方法安全降级（打印告警并跳过，不抛错）。\n\n## 兼容性\n\n### Vue / vue-router 版本\n\n| 依赖                   | 支持版本 | 说明                                                                                                                          |\n| ---------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |\n| Vue 3                  | `3.x`    | `./vue3` 子入口：`app.use(ArmsRumVue, ...)` + `useRum()` + `this.$rum`                                                        |\n| Vue 2.7                | `2.7`    | `./vue2` 子入口（examples 有 2.7.16 + vue-router 3.6.5 实测冒烟工程）                                                         |\n| Vue 2.6                | `2.6`    | `./vue2` 子入口。无 Composition API 不影响本插件 —— vue2 入口本就不提供 `useRum`，组件内用 `this.$rum` 或导入 `getRum()` 单例 |\n| `@vue/composition-api` | 不支持   | Vue 2 + composition-api 插件场景请使用 `./vue2` 入口 + `getRum()`（不提供经该插件的 `useRum` 形态）                           |\n| vue-router             | `3 \\| 4` | optional；插件仅依赖 `afterEach` 最小接口（`AnyRouter`），不包装 `createRouter`、不替换任何 import                            |\n\n### 打包器与消费形态\n\n| 环境                  | 支持情况    | 说明                                                                                                                                                                                                                                                                                                                                                                   |\n| --------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Vite / webpack 5 等   | ✅          | 经 `exports` 字段解析 `./vue2` / `./vue3` 子入口（types/import/require/default 四条件）                                                                                                                                                                                                                                                                                |\n| webpack 4             | ✅ 存根兜底 | webpack 4 不识别 `exports` 字段，包根提供 `vue2.js` / `vue3.js` 同名 CJS 存根（含于 `files`），旧构建链可直接 `require('@arms/rum-browser-vue/vue2')` 解析；同时配对提供根级 `vue2.d.ts` / `vue3.d.ts` 类型存根（`export *` 转发 `es/entries/` 入口全部具名导出，含于 `files`），`moduleResolution: \"node\"`（经典模式）的 TS 工程亦有完整类型，子路径 API 不回落 `any` |\n| CDN / `<script>` 标签 | ❌ 不适用   | 本包不出 UMD dist 产物，仅经 bundler 消费 —— 与主包 CDN 全局模式互斥；CDN 场景请直接使用主包 `@arms/rum-browser`（自动 PV + 全局异常采集，无 Vue 专属能力）                                                                                                                                                                                                            |\n\n> **产物压缩说明**：`es` / `lib` 产物已经过 terser 压缩与混淆，且**不附带 sourcemap**（与 browser-react 包一致的体积/混淆 trade-off）。排查线上堆栈时请对照仓库源码与 [CHANGELOG](./CHANGELOG.md) 版本定位对应发布版本。\n\n### SSR / Nuxt\n\n- **模块级 `import` 安全**：源码零顶层 `window` / `document` 访问（唯一 DOM 触点 `getCurrentUrl` 在函数内 try-catch 防护，非浏览器环境返回空串），服务端模块加载不会抛错；\n- **`install` 须在客户端生命周期调用**：Nuxt 场景请在 client plugin（如 `plugins/rum.client.ts`）中完成 `armsRum.init()` 与 `nuxtApp.vueApp.use(ArmsRumVue, { rum, router: nuxtApp.$router })`；\n- 无 Nuxt 专属适配（文件路由命名归一、`app:error` 启动错误钩子），按普通 Vue 3 方式接入可用但丢失 Nuxt 专属观测语义（列入后续演进）。\n\n## 已知限制\n\n> 以下限制是当前 MVP 设计所固有的，后续版本计划改进。\n\n### 单实例约束\n\n插件为 collector 级单例（模块级状态持有 shell/ctx 引用）。向已绑定的插件重复传入**另一个** rum 实例时（多 app 传入不同 `options.rum`），插件会打印 `logger.warn` 提示（`vue plugin is bound to another rum instance, only a single SDK instance is supported, refreshing shell reference`）并跳过重复注册、仅刷新 shell 引用 —— 最后一次绑定的实例生效，`$rum` / `useRum()` / `addVueError` 的上报会路由到该实例。微前端多子应用各自持有独立 RUM 实例的场景暂不支持，未来版本计划评估注入形态解除该限制。\n\n### `source='vue'` 错误不受 `collectors.jsError` 采样管控\n\n通过插件接管或 `addVueError` 上报的 Vue 错误携带 `source: 'vue'`。browser SDK 的 `SessionProcessor` 采样键映射当前仅覆盖 `console` / `onError` / `unhandled` 三类 source（`'vue'` 不在其中），这意味着这些错误会绕过 `collectors.jsError` 采样配置。如需禁用 Vue 错误上报，请使用 `collectors.exception`（设置为 `false`）。后续版本可能会在 browser session-processor 中新增 `'vue'` → `'js'` 的 source 映射。\n\n### errorHandler 覆盖边界\n\n插件仅接管 `config.errorHandler`（Vue 3 `app.config.errorHandler` / Vue 2 `Vue.config.errorHandler`，链式保留原 handler）。以下边界场景不在覆盖范围内：\n\n- **组件 `errorCaptured` 返回 `false`**：按 Vue 语义该错误被视为\"已处理\"并阻止继续传播，全局 `errorHandler` 不会被调用 —— 插件捕获不到此类错误（Vue 框架行为，非插件可拦截）；\n- **`warnHandler` 不覆盖**：Vue 运行时警告（如 prop 校验失败）不会进入 RUM 异常事件；\n- **`unhandledrejection`**：Promise 未捕获拒绝由主包 `@arms/rum-browser` 的 jsError 采集器覆盖，无需本插件处理。\n\n### 初始化时序\n\n插件接入（`app.use(ArmsRumVue, ...)` / `Vue.use(ArmsRumVue, ...)`）不再依赖 `armsRum.init()` 完成 —— 可在 init 前后任意时序同步调用，先后顺序可互换。初始化完成之前调用 `useRum` / `$rum` 的 `sendCustom` / `sendEvent`、或 `addVueError` 等需 shell 的能力时，将安全降级（打印告警并跳过操作，不抛错），init 完成前触发的错误与自定义事件不会被采集。init 前触发的路由导航经插件内部 pending 队列兜底，`collector.setup` 完成后自动补发首个 view（`loading_type: 'initial_load'`），首屏不丢失。`useRum()` / `getRum()` 本身可在任意时刻调用 —— 它们返回稳定单例引用，在初始化完成后即可正常使用。\n\n## License\n\nISC\n","readmeFilename":"README.md"}