Nuxt 接入(@tripo3d/lens/nuxt)
@tripo3d/lens 的 Nuxt 适配器,把 初始化 · 框架接入 的客户端接线与 SSR 采集 · 环境 1 的服务端 Nitro 接线打包成一个 Nuxt Module,并自动落地 SSR方案(服务端只采集、客户端统一发)。
它提供两种接入模式:
- 模式 A · 适配器托管——零手工接线,适配器创建客户端实例并 provide 成
$tripoLens,开箱即用。 - 模式 B · 自带实例——核心 SDK 当普通库自己
new,适配器只接服务端 SSR、不碰客户端。
安装
pnpm add @tripo3d/lensnpm install @tripo3d/lensyarn add @tripo3d/lensNuxt 适配层已折入 @tripo3d/lens core(子路径 @tripo3d/lens/nuxt),无需单独安装适配器包;core 把 nuxt(^4)/ @nuxt/kit / h3 / nitropack 声明为 optional peerDependencies,Nuxt 工程内天然满足(module 兼容声明为 nuxt >=3.0.0)。
选择接入方式
| 维度 | 模式 A · 适配器托管(默认) | 模式 B · 自带实例(client: false) |
|---|---|---|
| 客户端实例 | 适配器自动创建 | 你自己 new TripoLens |
| 取用实例 | useNuxtApp().$tripoLens | import 你的模块单例 |
app / configUrl / endpoint | 写在 tripoLens(必填) | 由你的实例提供(模块配置可省) |
| 适配器职责 | 客户端实例 + 服务端 SSR | 仅服务端 SSR |
| 何时选 | 开箱即用、无需自定义实例 | 要完全掌控插件 / fetch / onError,或把 SDK 当普通库独立用 |
| 配置 | 默认(client 省略) | tripoLens: { client: false } |
两种模式的服务端 SSR 采集完全相同(见下文 SSR 采集机制),区别只在客户端实例由谁创建。
模式 A:适配器托管(默认推荐)
在 nuxt.config 配三个必填项,适配器自动创建客户端实例、provide 成 $tripoLens,并接好服务端 SSR——业务零接线。
最小接入
nuxt.config.ts 注册 module,并在顶层 tripoLens key 下配置:
export default defineNuxtConfig({
modules: ['@tripo3d/lens/nuxt'],
tripoLens: {
// 必填:event_format App 段 → <app>.Perf / <app>.Error
app: 'shop',
// 必填:远端配置 CDN 地址
configUrl: 'https://cdn.example.com/lens/config.json',
// 必填:完整上报地址(含路径),由业务方给定
endpoint: 'https://collect.example.com/report',
},
})默认即装配归因 + 身份绑定 + 性能监控(含 SSR 渲染性能)+ 错误收集(含 SSR 服务端错误)+ 行为埋点。客户端注水后自动上报,服务端渲染性能经方案 D 注入 HTML、客户端统一发。
配在顶层 tripoLens,不要直接写 runtimeConfig
配置 key 是 nuxt.config 顶层的 tripoLens。Module 会在 setup 阶段把它规范化后写入 runtimeConfig.public.tripoLens 下发到客户端——你自己直接配 runtimeConfig.public.tripoLens 会被 module 覆盖。
模块配置项
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
app | string | — | 必填。event_format 的 App 段,决定上报类型前缀(如 <app>.Perf / <app>.Error)。缺失或空白会在构建/启动期抛错。 |
configUrl | string | — | 必填(client !== false 时)。远端 JSON 配置的 CDN 完整 URL。与 app / endpoint 一致,缺失或空白会在构建/启动期抛错;client: false 模式由你自带实例提供,可省。 |
endpoint | string | — | 必填(client !== false 时)。完整上报地址(含路径)。SDK 已移除内置默认,缺失会在构建/启动期抛错;client: false 模式由你自带实例提供,可省。 |
performance | boolean? | true | 装配 PerformancePlugin:Web Vitals / Navigation / LongTask / 慢资源。SSR 渲染 waterfall 另由 captureSsrPerf 控制。 |
errors | boolean? | true | 装配 ErrorPlugin:js / promise / 资源 / 白屏错误。Nuxt 适配器默认开(核心 SDK 仍 opt-in)。 |
captureSsrErrors | boolean? | true | 在 errors 基础上额外采集 SSR 服务端错误(归 ssr 子类)。需 errors: true 同时为真才生效。 |
captureSsrPerf | boolean? | true | 在 performance 基础上额外采集 SSR 渲染性能 waterfall(归 ssr.render / ssr.request)。需 performance: true 同时为真才生效。 |
tracking | boolean? | true | 装配 TrackingPlugin({ autoTrack: true }):点击 / 曝光 / PageView / 声明式 data-trace。Nuxt 适配器默认开(核心 SDK 仍 opt-in)。 |
client | boolean? | true | 适配器是否创建客户端实例。设 false 切换到模式 B:只接服务端 SSR、客户端实例自带,此时 app / configUrl / endpoint 均可省。 |
默认装配的能力
归因与身份始终开启;Nuxt 适配器下性能 / 错误 / 埋点默认全开(performance / errors / tracking 默认 true),零接线开箱即用。
「默认全开」是 Nuxt 适配器特有
直接用核心 @tripo3d/lens 时,ErrorPlugin / TrackingPlugin 仍是 opt-in(要手动 new ErrorPlugin() / new TrackingPlugin() 装配);Nuxt 适配器为了零接线体验把它们默认打开,不需要的项目用 errors: false / tracking: false 关掉即可。
三条容易踩的依赖关系:
- PageView / 声明式埋点随
tracking(默认开):适配器没有额外监听 vue-router,PageView 自动上报与data-trace采集都来自TrackingPlugin({ autoTrack: true });默认即开,不需要时设tracking: false关闭。 captureSsrErrors依赖errors:它只是透传给ErrorPlugin的开关;若errors: false,整个ErrorPlugin都不会装,captureSsrErrors形同虚设。captureSsrPerf依赖performance:它只是透传给PerformancePlugin的captureSsr开关;PerformancePlugin的 SSR 采集默认关,不开captureSsrPerf就只有普通性能、没有 SSR 渲染 waterfall。若performance: false,整个插件都不装,captureSsrPerf形同虚设。
想采集 SSR 服务端错误,两个都要开
tripoLens: { app: 'shop', configUrl: '...', errors: true, captureSsrErrors: true }组件内拿到实例
适配器把 TripoLens 实例 provide 成 $tripoLens,在任意组件 / composable 里用 useNuxtApp() 取:
<script setup lang="ts">
const { $tripoLens } = useNuxtApp()
// 示例:登录后绑定身份(identify 始终可用)
$tripoLens?.identify('user-123', { plan: 'pro' })
</script>拿到实例后,各上报方法的语义与参数见对应模块页,本页不重复:
| 能力 | 方法 | 前置 | 文档 |
|---|---|---|---|
| 身份绑定 | identify | 始终可用 | 身份与会话 |
| 命令式埋点 | track / click / expo / pageview | tracking: true | 行为埋点 |
| 曝光进阶 | trackImpression / setExposurePolicy | tracking: true | 行为埋点 · 进阶 |
| 手动捕获 | captureException / captureMessage | errors: true | 错误收集 |
| 手动性能 | startTransaction | performance: true | 性能收集 |
$tripoLens 仅在客户端存在
运行时 plugin 是 .client 的,实例只在浏览器侧创建。SSR 渲染期间 useNuxtApp().$tripoLens 为 undefined。不要在 <script setup> 顶层、asyncData / 中间件等可能跑在服务端的位置无保护地调用——放到事件回调、onMounted,或先判空:
const { $tripoLens } = useNuxtApp()
$tripoLens?.identify('user-123')TypeScript 类型增广:适配器目前未对 $tripoLens 做类型增广,直接取会是未类型化的。可在工程内补一个声明文件(如 types/tripo-lens.d.ts):
import type { TripoLens } from '@tripo3d/lens'
declare module '#app' {
interface NuxtApp {
$tripoLens: TripoLens
}
}
export {}模式 B:自带实例 + 仅服务端扩展(client: false)
想把核心 SDK 当普通库独立用(自己掌控插件 / fetch / onError),又复用适配器的服务端 SSR 接线,设 client: false:适配器只注册 Nitro 服务端 plugin,不创建任何客户端实例。这样实例与扩展彻底正交、不会冲突。
关键点:SSR 数据在客户端实例 init 时自动消费——PerformancePlugin({ captureSsr: true }) 与 ErrorPlugin({ captureSsr: true })(两个 captureSsr 都默认关,需显式打开)在 setup() 里就会读取服务端注入的 __TRIPO_SSR_PERF__ / __TRIPO_SSR_ERR__ 容器并上报。不需要任何 Nuxt plugin 胶水,也不必把 new 写进 defineNuxtPlugin。
// app/utils/lens.ts —— 标准 SDK 用法,与框架无关
import { ErrorPlugin, PerformancePlugin, TripoLens } from '@tripo3d/lens'
export const trace = new TripoLens({
app: 'shop',
configUrl: '...',
endpoint: '...',
plugins: [
new PerformancePlugin({ captureSsr: true }),
new ErrorPlugin({ captureSsr: true })
],
})
await trace.init() // SSR 下 no-op;客户端 init 时自动消费 SSR 容器// nuxt.config.ts —— 扩展只搬运服务端 SSR,不碰客户端
export default defineNuxtConfig({
modules: ['@tripo3d/lens/nuxt'],
tripoLens: { client: false }, // 此时 app / configUrl / endpoint 由你的实例提供,模块配置可省
})之后任意组件 / 工具里 import { trace } from '~/utils/lens' 直接调用即可,无需 useNuxtApp()。
注水耗时 span 是可选项
不写任何客户端胶水时,SSR 渲染 waterfall 与服务端错误都会正常上报,只少一条 hydration 注水耗时 span。需要它就在根组件补一行(仍无需把 new 放进 plugin):
// app.vue
import { trace } from '~/utils/lens'
onMounted(() => trace.markHydration())客户端只能有一个实例
SSR 容器是读后即清,且自动采集(Web Vitals / 错误 / PageView / 网络计时)每个实例各跑一套。所以别让适配器默认实例与自建实例并存:自带实例就设 client: false(关掉适配器那个),否则会双实例重复上报、且 SSR 容器被先 init 的一方消费清空、另一方拿空。反过来,用默认适配器实例时就不要再自己 new。
控制初始化时机
渠道归因要求实例在业务任何 URL 操作之前构造。模块单例在被首次 import 时求值,所以请尽早 import(如在 app.vue 顶层,或一个只写 import '~/utils/lens' 的早序号 .client plugin——该 plugin 不 new、只触发模块求值)。
SSR 采集机制(两种模式共用)
无论哪种模式,服务端 SSR 采集都由 module 自动接的 Nitro server plugin 完成,业务零服务端代码:
- Module setup 强制开启
nitro.experimental.asyncContext = true,使渲染期出站请求能经useEvent()回查归属到当前请求。 - 每个请求在
event.context上挂带renderId的性能采集器与错误缓冲;渲染期所有出站请求(含业务$fetch.create()派生实例——底层仍走原生 fetch)经被 patch 的globalThis.fetch计时包装归属到当前请求 collector,记成ssr.request,可重建 waterfall。 render:htmlhook 自动注入window.__TRIPO_SSR_PERF__/__TRIPO_SSR_ERR__两个独立容器。- 客户端实例 init 时,
PerformancePlugin/ErrorPlugin自动读取上述容器并展开上报(ssr.render/ssr.request/ 服务端错误,带同renderId)。
「客户端读取」在两种模式下:
- 模式 A:由适配器创建的客户端实例自动完成;适配器的 client plugin 还在
app:suspense:resolve调markHydration(),额外产一条hydration注水耗时 span。 - 模式 B:由你自己的实例 init 时完成;
hydrationspan 为可选(见模式 B 的「注水耗时 span」)。
机制细节与后端对接字段见 SSR 采集。
故障排查
| 症状 | 原因 | 处理 |
|---|---|---|
构建 / 启动直接报错(app / endpoint / configUrl 必填) | 三项任一缺失或为空白(client !== false 时) | 在 tripoLens 下补齐非空的 app / endpoint / configUrl |
组件里 $tripoLens 是 undefined | 代码跑在 SSR 期 | 见模式 A「仅在客户端存在」,判空或移到客户端时机 |
开了 captureSsrErrors 却没 SSR 错误数据 | errors 没开,ErrorPlugin 根本没装 | 同时设 errors: true |
开了 captureSsrPerf 却没 SSR 性能数据 | performance: false 关了插件,或没开 captureSsrPerf | 确保 performance 不为 false 且 captureSsrPerf: true |
| 点击 / PageView 没上报 | tracking 没开 | 设 tracking: true |
| 事件 / SSR 数据翻倍或丢失 | 适配器默认实例与自建 new 实例并存(双读取方) | 自带实例时设 client: false |
| SSR 出站请求归属错乱 / waterfall 断裂 | 工程自行关掉了 nitro.experimental.asyncContext | 不要覆盖该项(module 已自动开启) |
下一步
- 行为埋点:声明式
data-trace与命令式 API 的完整能力。 - SSR 采集:方案 D 的机制、上报字段与非 Nuxt 环境接线。
- 远程配置:
configUrl下发的配置如何控制采样与开关。 - 不便用适配器时:手写接入见 初始化 · 框架接入 与 SSR 采集 · 环境 1,本适配器即这两节的打包版。