@tengence/track-sdk-web
Tengence Web 行为埋点 SDK。上报统一走 Authorization: Bearer,凭证三选一:apiKey 直连(配置即用,不请求鉴权地址)、authUrl 自动换取(SDK 内部获取并管理短期 accessToken)、setToken 外部注入(覆盖内部 token)。推送地址内置默认,可初始化覆盖。
安装与引入
UMD:
<script src="https://static.tengence.com/track/tengence-track-sdk@1.1.13.js"></script>
初始化
方式一:authUrl 自动换取 accessToken(推荐,无长期密钥暴露)
配置鉴权地址后,SDK 首次上报前自动向 authUrl 换取短期 accessToken,缓存复用(localStorage + 内存),401 时自动清缓存重新获取并重试一次,无需业务方干预。
const client = TrackSDK.init({
authUrl: "https://www.tengence.com/wp-json/tengence/v1/auth/access-token?module=track",
platform: "web",
traceBehavior: true,
traceError: true,
tracePerformance: true,
});
方式二:apiKey 直连(无鉴权服务 / 简单场景)
const client = TrackSDK.init({
apiKey: "sk-xxxxxxxx",
platform: "web",
});
方式三:外部 setToken 注入 accessToken
外部调用方已有自己的 token 体系时,初始化后随时注入,注入的 token 覆盖 SDK 内部获取的 token(仅内存,不持久化):
const client = TrackSDK.init({ platform: "web" });
client.setToken("<外部短期 accessToken>");
client.setToken();
凭证要求:apiKey、authUrl、setToken 至少提供其一,否则 SDK 无法获取上报凭证,初始化与上报时会提示错误且不推送数据(数据保留在缓存队列)。
推送地址:pushUrl 不传时使用内置默认地址 https://api.tengence.com/v1/push/event,私有化 / 多环境可显式覆盖。
凭证优先级:apiKey > 外部 setToken 注入 > authUrl 内部换取。
上报事件
v1.1.12 起主 API 为 track(对齐 Segment / Mixpanel / Amplitude 主流 track(event, properties)),原 report 已移除(破坏性变更,见下方迁移说明):
client.track("click", { id: "btn-1", name: "提交" });
client.track("pay", { order: "x" }, { data_type: "custom", track_real_time: true });
client.track({
event_type: "click",
data_type: "behavior",
event_detail: { id: "btn-1", name: "提交" },
spm: "a.b.c",
});
手动立即上报:await client.flush() —— 立即触发普通 + 实时两通道发送,返回 Promise 等待在途发送完成(无数据时立即 resolve);适合跳页/退出前主动冲刷,对齐 Amplitude / 神策 flush()。
report → track 迁移:对象形式 report({...}) 直接改为 track({...}),参数与语义不变;原 report 已从 client 与 window.trackMonitor 移除。
TrackSDK 全局仅暴露 init;track / flush / setToken / registerGlobalProperties 等方法通过 init 返回的 client 实例调用(也可经全局 window.trackMonitor 访问)。
注册全局扩展属性
对每个事件都想携带的稳定属性(如语言、货币、AB 分组),初始化后调用一次 registerGlobalProperties,注册时即提供值;SDK 内部将注册字段组装进 register_properties 字段自动随每个事件上报,业务侧无需每次 track 手动携带,也看不到该字段。未注册的扩展字段不会被上报(由 SDK 端过滤)。
client.registerGlobalProperties({
language: "zh-CN",
currency: "CNY",
});
- 注册即提供值;重复注册同名键以最新值为准;localStorage 持久化,跨会话保留
- 键数上限 50,超限部分丢弃并告警
- 每次上报时动态变化的业务值(金额、折扣等)请放在
track() 的 event_detail 中携带,无需注册
字段说明
pushUrl | 推送地址,默认 https://api.tengence.com/v1/push/event(原 url 改名) |
authUrl | 鉴权地址(获取 accessToken),无默认值;配置且未配 apiKey 时 SDK 内部自动换取;authUrl 服务所需特定参数(如 module=track)请放入地址查询串(如 ...?module=track),SDK 请求体固定为空对象 {} |
apiKey | 应用长期 apiKey(sk-)直连优先,配置后不再请求 authUrl |
platform | 终端维度:web / h5 / ios / android / wechat_miniprogram / alipay_miniprogram,缺省按 UA 推断 |
cacheNumber | 缓存条数触发上限,默认 100 条(100 条或 5 秒触发上报,先到先发) |
reportInterval | 普通通道上报周期,默认 5000ms(5 秒)(对齐 Mixpanel/Segment 主流批量窗口) |
maxCacheSize | 缓存体积触发上限,默认 56KB(与 fetch keepalive 64KB 上限兼容) |
maxRetries | 最大重试次数,默认 10;耗尽后数据保留队列(不丢弃),console.warn 提示 |
realTimeUrl | 实时推送地址,无默认值;未配置时实时事件并入普通通道上报(单份、不丢、不双写);配置后实时事件走独立实时通道(200ms 快发,按 realTimeReportInterval) |
realTimeReportInterval | 实时通道上报周期,默认 200ms |
errorTraceRate | 错误采样率,默认 0.5(50%);传 0 关闭错误上报、传 1 全量上报(v1.1.8 起显式 0/1 生效) |
sanitize | 发送前 PII 脱敏(默认关闭,业务按需显式开启):传入对象开启——stripQuery 剥离 URL 查询串(默认 true)、maxTextLength 超长文本截断(默认 0 关闭,0 关闭截断)、preserveQueryKeys 剥离时保留的键;传 false 显式关闭 |
enableAutoSessionId | 会话自动维护开关,默认 false:外部未传 session_id 时,开启则 SDK 维护 30min 空闲超时会话(超时自动重置新 id,活跃顺延);关闭则不带 session_id |
enableTracking | 采集总开关,默认 true(v1.1.11):传 false 初始化或 client.enableTracking(false) 即退出采集(opt-out)——后续 track 忽略、清空本地与实时未上报队列(合规语义:退出后不再持有/上报任何数据)、停止一切发送(含周期定时、卸载补发);client.enableTracking() 无参返回当前状态,client.enableTracking(true) 恢复采集。开关状态持久化 localStorage,刷新后保持 |
enableScroll | 滚动深度采集开关,默认 true(v1.1.13):到达 25%/50%/75%/90% 深度各上报一次 scroll 事件(每档仅一次,90% 后解除监听);false 关闭 |
enableFormTrack | 表单交互采集开关,默认 true(v1.1.13):自动上报 form_start(表单内控件首次 focus,每表单一次)/ form_submit(每次提交);只采表单元数据(id/class/name/action/可见文本),不采 input 值(隐私安全,神策同策略) |
requestTimeout | 单次上报请求超时,默认 10000ms(v1.1.11),范围 [1000, 60000]:fetch 用 AbortController、XHR 用 timeout 兜底;超时数据保留队列按退避重试;页面卸载补发(pagehide/beforeunload)不设超时(keepalive 兜底不被 abort 中断) |
onError(error) | SDK 自身错误回调(v1.1.11,默认无):error 形如 { code, message, context? },详见下方错误码表;与 onDrop 职责分离——onDrop 感知数据面(滞留/丢弃),onError 感知系统面(配置缺失、token 获取/失效、队列读写失败、请求超时等 SDK 内部故障);回调内抛错不影响 SDK 主流程 |
beforeSend(events) | 发送前钩子:返回修改后的事件数组(Segment middleware 风格,业务自定义增删/脱敏) |
onDrop(events, reason) | 数据滞留/丢弃回调(默认无):reason 为 rejected_4xx(4xx 拒绝,含单条 413 超限)/ retries_exhausted(重试耗尽)/ item_too_large(单条超限丢弃)/ queue_overflow(队列超上限丢最旧)/ server_rejected(v1.1.10:网关 200 + rejected_ids 校验明确拒绝,从队列移除并通知);业务可编程感知失败,不改变保留语义 |
client.setToken(token) | 注入外部 accessToken(覆盖内部获取;传 undefined 清除,回退 apiKey/authUrl) |
client.track(eventType, eventDetail?, options?) | 上报主 API(v1.1.12):字符串形式 track("click", {id:1}) / 对象形式 track({event_type,...}) 兼容全字段;options 透传 data_type/session_id/request_id/spm/track_real_time/platform |
client.flush() | 手动立即上报(v1.1.12):触发普通+实时两通道发送,返回 Promise 等待在途发送完成 |
client.registerGlobalProperties(props) | 注册全局扩展属性(注册即提供值),SDK 内部组装进 register_properties 上报,用户不可见 |
上报队列与重试机制
- 双通道:普通通道(批量)与实时通道(快发)两条独立队列,均 localStorage 持久化;实时通道仅在配置
realTimeUrl 后启用,未配置时实时事件并入普通通道(单份、不丢、不双写);所有类型事件(含错误)默认走普通通道,仅业务显式 track_real_time: true 的事件走实时通道(口子保留,待实时后台就绪后启用)
- 成功后清理:批量提交成功后才按该批
event_id 列表从队列移除;提交失败(任何原因)数据保留在队列,绝不丢弃。v1.1.10(N-4):网关响应含 accepted_ids/rejected_ids 时按服务端确认精确清理——只清被接收的条目;rejected_ids(服务端校验明确拒绝,永久性拒绝)从队列移除并触发 onDrop("server_rejected") 通知业务(对齐 Segment/Sentry:永久错误不重试);响应缺 ids(异常兜底)按整批成功清理 + warn,防死循环
- 触发时机:普通通道满 100 条 / 满 56KB / 每 5 秒定时(先到先发);实时通道 200ms 定时;定时器到点强制发送(v1.1.9 修复:原"定时到点仅检查不发送"导致低流量数据滞留)
- 重试:普通/实时通道独立计数(互不阻塞);指数退避 + 抖动(封顶 60s),429 尊重
Retry-After;HTTP 已响应的 4xx/5xx 不重复回退请求;其他 4xx(数据被拒)标记滞留保留、不自动轰炸;重试耗尽后数据保留并 warn;413(PayloadTooLarge)自动降容:批次减半重发(对齐 Amplitude/Mixpanel),单条仍超限才滞留
- 失败感知:
onDrop(events, reason) 回调(v1.1.9 起)——rejected_4xx/retries_exhausted/item_too_large/queue_overflow;v1.1.10 新增 server_rejected(网关 200 + rejected_ids 校验拒绝,从队列移除并通知);传输失败类数据仍按保留原则处理
- 卸载兜底:beforeunload + pagehide + visibilitychange(hidden) 三重尽力补发;keepalive 超 64KB 自动切片分批;网络恢复(online)立即补发
- 凭证:apiKey > 外部 setToken 注入 > authUrl 内部换取(缓存复用 + single-flight + 401 自动刷新一次)
- 会话:
session_id 调用方显式传入优先;未传且开启 enableAutoSessionId(默认关闭)时,SDK 自动维护 30min 空闲超时会话(sessionStorage,30min 无活跃则重置新 id,活跃顺延)
- 脱敏:默认关闭(业界主流,业务按需显式开启)——显式传
sanitize: { stripQuery, maxTextLength, preserveQueryKeys } 后,发送前剥离 page_url 及 URL 类字段查询串、超长文本截断;sanitize: false 显式关闭;也可用 beforeSend 钩子自定义
- 隐私合规(opt-out):
enableTracking 采集总开关(v1.1.11,默认 true),client.enableTracking(false) 退出采集——后续事件忽略、清空本地与实时未上报队列、停止一切发送(含周期/卸载补发),对齐主流(Amplitude/Mixpanel opt-out 语义);开关持久化,刷新保持
- 隐私合规(GPC,v1.1.14):浏览器"全局隐私控制"信号(
navigator.globalPrivacyControl === true,用户在浏览器层选择不出售/不分享数据)自动等效于退出采集——作为叠加关闭层:事件不入队、不发请求;init 时读取一次 + 每次上报前复查(浏览器无 GPC 变化事件);respectGpc: false 关闭信号响应(默认 true);GPC 不覆写持久化的 enableTracking(二者独立叠加,任一关闭即停采;即使 enableTracking(true) 恢复,GPC 仍开启时采集保持关闭)
- 请求超时:单次请求默认 10s(v1.1.11,范围 [1s, 60s]),fetch AbortController + XHR timeout 双保险;超时保留队列按退避重试;页面卸载补发不设超时(keepalive 不被 abort 中断)
- 多标签页:队列基于 localStorage,多标签页同时写入可能互相覆盖(last-write-wins);建议单标签页使用,服务端已按
event_id 去重
- 队列性能(v1.1.12):内存镜像为主数据源 + 增量字节统计,入队 O(1);落盘 200ms 防抖合并写(多次入队合并一次序列化,取代原每次入队全量 parse+stringify 的 O(n²));成功清理路径立即落盘(页面清理后瞬间崩溃不残留已提交批次,避免下次会话重复发送);页面关闭/隐藏(beforeunload/pagehide/visibilitychange hidden)强制同步落盘,崩溃窗口 ≤200ms;隐私模式 localStorage 不可用时数据仅保留内存、镜像不丢
SDK 错误码(onError 回调,v1.1.11)
init_missing_credential | 初始化/上报时未配置 apiKey、authUrl 且未 setToken | 本批不上报,数据保留队列待重试 |
token_fetch_failed | 从 authUrl 换取 accessToken 失败(网络/响应缺字段) | 本批不上报,数据保留队列待重试 |
token_invalid | 上报 401/403 后自动刷新 accessToken 仍失败 | 本批不上报,数据保留队列待重试 |
request_timeout | 上报请求超时(fetch abort / XHR timeout) | 数据保留队列按退避重试 |
queue_read_failed | 读取 localStorage 队列失败(损坏 JSON 等) | 按空队列处理 |
queue_write_failed | 写入 localStorage 队列失败(隐私模式/容量满) | 队列清空处理(尽力兜底) |
localstorage_unavailable | localStorage 完全不可用(隐私模式) | 本次数据仅保留内存 |
enqueue_failed | 事件入队失败 | 该事件丢弃 |
自动采集事件(全埋点,v1.1.13 补全)
traceBehavior: true(默认)时自动采集以下事件,无需业务手动 track:
page_view | 页面加载 / hash 变化 / pushState / replaceState / popstate(v1.1.13 新增) | 200ms 防抖 + URL 去重;SPA 前进/后退补报页面浏览(对齐 GA4 监听 pushState/popState/replaceState) |
page_leave | 路由变化 / 页面隐藏 / 关闭 | 停留 >200ms 才报,携带停留时长 |
click | 预设标签 A/INPUT/TEXTAREA/BUTTON / track-click 属性 / closest('a, button, [track-click]') | 采集元素 id/class/name/type/XPath/坐标/占比 |
scroll(v1.1.13) | 滚动到达 25%/50%/75%/90% 深度 | 每档仅一次(300ms 节流 + Set 去重),90% 后解除监听;enableScroll: false 关闭 |
form_start(v1.1.13) | 表单内控件首次 focus | 每表单仅一次;只采表单元数据不采 input 值;enableFormTrack: false 关闭 |
form_submit(v1.1.13) | 表单提交(捕获阶段) | 每次提交上报,含 submitter 信息;只采表单元数据不采 input 值 |
expose / view / view_expose | 元素进入可视区(IntersectionObserver) | 可视区停留默认 500ms(data-duration-view/data-duration-expose 可逐元素覆盖) |
v1.1.14 变更(自 v1.1.13)
| GPC 隐私信号(第四批 G4) | 新增 respectGpc(默认 true):浏览器全局隐私控制信号开启(navigator.globalPrivacyControl === true)时自动等效退出采集(叠加关闭层,不入队、不发请求);init 读取一次 + 每次上报前复查;不覆写持久化 enableTracking;false 关闭信号响应 |
| 测试与 CI(N-5) | 新增 vitest + jsdom 自动化测试(24 用例:GPC 三态/叠加层、md5 向量、PII 脱敏、队列/重试语义、错误捕获、beforeSend/onDrop),npm test / npm run test:watch / npm run test:e2e(冒烟)/ npm run typecheck;GitHub Actions CI(push/PR:build → test → typecheck → e2e,tag 与 package.json 版本一致性发布门) |
| 脱敏修复(M-15) | 修正 stripQuery 独立生效:原实现仅 maxTextLength > 0 时才剥 detail 内 URL 类字段查询串(开启 stripQuery 但未设截断时静默失效);现开启脱敏即剥离,文本截断按 maxTextLength 各自独立 |
v1.1.13 变更(自 v1.1.12)
| 滚动深度采集(P0-①) | 新增 enableScroll(默认 true)+ scroll 事件:滚动到达 25%/50%/75%/90% 深度各上报一次(300ms 节流、每档 Set 去重、90% 后解除监听);深度算法 round((scrollTop+视口高)/文档高×100);对齐 GA4 Enhanced Measurement scroll 深度 + 业界多阈值(GA4 仅 90% 单档) |
| 页面浏览补报(P0-②) | page_view 新增 popstate 监听(复用 200ms 防抖 + URL 去重):浏览器前进/后退(SPA history 模式)补报页面浏览;与现有 pushState/replaceState/hash 上报互补不重复;对齐 GA4 监听 popState |
| 跨域 Script error 归一化(P0-③) | 修复跨域脚本未加 crossorigin 时的 Script error 丢失(原 getErrorKey 判为 "cors" 且无分支处理):归一化为 js 错误上报,统一指纹 js-Script error. 全站去重为一条(防刷屏),meta 标注 crossorigin_missing: true,不伪造堆栈;README 建议生产脚本加 crossorigin="anonymous" 获取完整堆栈;对齐 Sentry Script error 归一化 |
| 表单交互采集(P1-④) | 新增 enableFormTrack(默认 true)+ form_start/form_submit 事件:focusin 委托捕获表单控件首次 focus(每表单一次防刷屏)+ submit 捕获阶段每次提交(含 submitter_id/text);只采表单元数据,不采 input 值(隐私安全,神策同策略);document 级事件委托自动覆盖动态表单;对齐 GA4 form_start/form_submit |
| 冒烟测试 | 新增 S(scroll 四档各一次/不重复)、P(popstate 补报 page_view)、E(Script error 归一化/去重/不伪造堆栈)、F(form_start 去重/form_submit/不采 input 值),38/38 全绿;mock 升级:多槽监听收集(对齐真实浏览器同事件多回调)+ ErrorEvent polyfill |
v1.1.12 变更(自 v1.1.11)
主 API 改 track(破坏性变更) | 移除 report(client 与 window.trackMonitor 均无),主 API 改为 track(eventType, eventDetail?, options?),对齐 Segment/Mixpanel/Amplitude 主流签名;字符串形式 track("click", {id:1}) + 对象形式 track({event_type,...}) 兼容全字段;options 透传 data_type/session_id/request_id/spm/track_real_time/platform。迁移:report({...}) → track({...}),参数语义不变 |
新增 flush() | client.flush(): Promise<void>:立即触发普通+实时两通道发送,返回 Promise 等待在途发送完成(无数据立即 resolve);跳页/退出前主动冲刷,对齐 Amplitude/神策 |
| 队列性能优化 | 内存镜像 + 增量字节,入队 O(1)(原每次入队全量 parse+stringify 的 O(n²));落盘 200ms 防抖合并写;成功清理立即落盘(崩溃不残留已提交批次);页面关闭/隐藏强制同步落盘,崩溃窗口 ≤200ms;隐私模式仅内存不丢镜像。条数/体积/周期/成功才清理/onDrop 语义不变 |
| 冒烟测试 | 全量迁移 report→track + 新增 F1(flush 立即上报/等待在途)、T1(track 字符串/对象/options 三形式),34/34 全绿 |
v1.1.11 变更(自 v1.1.10)
| 隐私合规 opt-out(G1) | 新增 enableTracking(默认 true)+ client.enableTracking(flag?):退出采集后事件忽略、清空本地与实时未上报队列、停止一切发送(含周期/卸载补发,beforeReport 加总闸);开关持久化 localStorage;命名遵循前端 enable* 规范 |
| 请求超时(G2) | 新增 requestTimeout(默认 10000ms,[1000, 60000]):fetch 用 AbortController、XHR 用 timeout 双保险;超时数据保留队列按退避重试;卸载补发(pagehide/beforeunload)不设超时(keepalive 兜底不被 abort 中断) |
| SDK 错误可观测(G5) | 新增 onError(error) 回调 + 错误码表(8 个 code):配置缺失、token 获取/失效、队列读写失败、请求超时、入队失败等系统面故障通知;与 onDrop 职责分离(数据面 vs 系统面);回调内抛错不影响 SDK 主流程 |
| 冒烟测试 | 新增 W1/W2/W3(opt-out 停止发送/恢复/清空队列)、X1(超时走退避重试 + onError)、X2(卸载补发无超时 signal)、Y1/Y2/Y3(onError 三场景),32/32 全绿;场景隔离升级(resetCalls 重置 SDK 幂等实例标记 + token 缓存过期控制) |
v1.1.10 变更(自 v1.1.9)
| 网关精确清理(N-4) | 响应新增 accepted_ids/rejected_ids(网关侧配套改造,部分接受不再整体 400):成功后只清理被服务端接收的条目;rejected_ids(校验类永久性拒绝,重发必再拒)从队列移除并 onDrop("server_rejected") 通知;响应缺 ids 时按整批成功清理 + warn(防死循环) |
| onDrop 新 reason | 新增 server_rejected(网关 200 + rejected_ids);rejected_4xx 保留(真实 HTTP 4xx 整体拒绝场景) |
| 冒烟测试 | 新增 V1(部分接受→精确清理 + server_rejected)/ V2(缺 ids 兜底),24/24 全绿 |
v1.1.9 变更(自 v1.1.8)
| 413 自动降容 | HTTP 413 PayloadTooLarge 不再当作普通 4xx 滞留:批次 >1 时减半重发(对齐 Amplitude/Mixpanel),成功后复位;单条仍超限才滞留保留(防死循环) |
| onDrop 回调 | 新增 onDrop(events, reason):rejected_4xx(4xx 拒绝,含单条 413 超限)/ retries_exhausted(重试耗尽)/ item_too_large(单条超限丢弃)/ queue_overflow(队列超上限丢最旧);业务可编程感知失败,不改变保留语义 |
| 定时器到点强制发送 | 修复"定时到点仅检查条数不发送"问题(低流量页面数据可能长期滞留):周期定时器到点即发送(时间触发),与"满 100 条 / 满 56KB / 每 5 秒"语义一致 |
| 冒烟测试 | 新增 T(413 降容)/ U(onDrop 四场景),22/22 全绿;场景隔离增强(resetCalls 清空 storage,避免前序滞留数据污染) |
v1.1.8 变更(自 v1.1.7)
| 配置 0 值生效 | cacheNumber/reportInterval/maxCacheSize/maxRetries/errorTraceRate 由 || 改 ??,显式传 0 不再被回填默认值(如 errorTraceRate: 0 关闭错误上报、maxRetries: 0 不重试);非法值回退默认并告警 |
| init 幂等 | 重复调用 init 复用首次实例并告警,不再叠加监听器/代理/Observer |
| PII 脱敏 | 新增 sanitize 配置与 beforeSend 钩子;默认关闭(业界主流),显式开启后剥离 page_url 及 URL 类字段查询串、超长文本截断 |
| 实时通道(修订) | 撤销"错误自动走实时":所有类型事件(含错误)默认走普通通道;仅业务显式 track_real_time: true 走实时(口子保留,待实时后台就绪) |
| 会话管理 | 新增 enableAutoSessionId(默认 false):外部未传 session_id 且开关开启时,SDK 自动维护 30min 空闲超时会话(sessionStorage,活跃顺延);调用方显式传入始终优先 |
| 网络恢复补发 | 监听 online 事件,断网恢复后立即 flush |
| 性能上报时机 | 性能指标(CWV)除 beforeunload 外,增加 pagehide / visibilitychange(hidden) 兜底(30s 防抖),缓解移动端丢失 |
| 日志开关持久化 | enableLogger/disableLogger 写入的持久化开关在 init 时生效(原只写不读,刷新失效) |
| 其他修复 | isVisible 反逻辑修正;错误去重数组 Set 化 + 上限 1000;md5 自检惰性化(模块加载零开销) |
v1.1.7 变更(自 v1.1.6)
| 批量默认参数 | cacheNumber 500→100 条、reportInterval 30s→5s(对齐 Mixpanel/Segment 主流批量窗口,低流量事件延迟 30s→5s) |
| 队列语义 | 提交成功后才按 event_id 清理该批;失败数据保留队列,绝不丢弃(原为"发送前清空队列,失败拼回") |
| 实时事件分发 | 仅配置 realTimeUrl 时走实时通道;未配置时并入普通通道(原为双写两条队列导致重复上报) |
| 重试机制 | 普通/实时通道独立计数;线性退避 → 指数退避 + 抖动 + Retry-After(封顶 60s);4xx/5xx 不再回退 XHR 重复请求;重试耗尽后数据保留 + warn(原为静默丢弃) |
| 队列上限 | 新增条数硬上限 2000 条(丢最旧)与单条体积上限 64KB(丢单条),替代"写满清空整队列" |
| 卸载兜底 | beforeunload + pagehide + visibilitychange(hidden);keepalive 超 64KB 自动切片 |
v1.1.6 破坏性变更与迁移(自 v1.1.5)
url 改名 pushUrl | 初始化配置 url 改为 pushUrl(默认值不变) |
初始化配置 accessToken 移除 | 不再初始化时传入;改由 client.setToken(token) 运行时注入 |
onTokenExpired 回调移除 | 无需配置:配置 authUrl 时 SDK 内部自动换取并在 401 后自动刷新重试;外部 token 生命周期由调用方自行管理 |
| 凭证要求收紧 | apiKey / authUrl / setToken 至少其一,否则提示错误且不推送 |
测试与 CI(v1.1.14)
- 单元与行为测试:vitest + jsdom(
npm test,watch 用 npm run test:watch),覆盖 GPC 三态与叠加层、md5 向量、PII 脱敏(stripQuery/preserveQueryKeys/maxTextLength/默认原文)、enableTracking 持久化、队列语义(入队最新在前、flush 成功清理、失败保留、满条立即触发)、beforeSend 过滤、onDrop(rejected_4xx)、错误捕获与 Script error 归一化
- 类型检查:
npm run typecheck(tsc --noEmit,覆盖 src + test)
- 端到端冒烟:
npm run test:e2e(scripts/smoke-test.mjs,mock 浏览器环境驱动 dist 产物,验证队列/重试/脱敏/会话/幂等/滚动/表单/错误全链路)
- CI:
.github/workflows/ci.yml——push/PR 触发:build → test → typecheck → e2e;vX.Y.Z tag 自动校验与 package.json version 一致(发布门,防错发)