SSR 框架下接入¶
RUM SDK 只能在浏览器环境初始化,不能在服务端渲染阶段执行。本页介绍 Next.js 和 Nuxt 的官方框架插件接入方式。
| 阶段 | 运行环境 | 是否初始化 RUM |
|---|---|---|
| SSR、Server Component 或 Nitro 执行阶段 | Node.js | 否 |
| Hydration 和客户端路由阶段 | Browser | 是 |
框架插件采集浏览器 View、资源、行为和客户端错误。纯服务端请求、Server Action、 Nitro 处理过程以及未传递到客户端的服务端错误,需要使用服务端监控方案。
版本要求
Next.js 和 Nuxt 框架插件从 RUM SDK 3.3.6 开始提供。RUM 主包版本不得低于 框架插件版本。
以下示例使用公网 OpenWay 的 site 和 clientToken。使用 DataKit 直连时,
将这两个参数替换为 datakitOrigin,不要同时配置两种上报地址。
Next.js¶
Next.js 插件支持 Next.js 13 及以上、React 18 及以上,以及 App Router 和 Pages Router。
安装¶
App Router:Next.js 15.3 及以上¶
Next.js 15.3 及以上支持 instrumentation-client.js|ts。该文件在 hydration
前运行,适合尽早初始化浏览器监控。
创建 instrumentation-client.ts;项目使用 src 目录时,将文件放在
src/instrumentation-client.ts:
import { datafluxRum } from "@cloudcare/browser-rum"
import {
nextjsPlugin,
onRouterTransitionStart,
} from "@cloudcare/browser-rum-nextjs"
export { onRouterTransitionStart }
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nextjs",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [nextjsPlugin()],
})
创建客户端 Router tracker:
// app/rum-router-tracker.tsx
"use client"
import { RumNextjsAppRouter } from "@cloudcare/browser-rum-nextjs"
export function RumRouterTracker() {
return <RumNextjsAppRouter />
}
在根 layout 中渲染一次:
// app/layout.tsx
import { RumRouterTracker } from "./rum-router-tracker"
export default function RootLayout({ children }) {
return (
<html lang="zh-CN">
<body>
<RumRouterTracker />
{children}
</body>
</html>
)
}
onRouterTransitionStart() 记录导航目标,RumNextjsAppRouter 等新 pathname
实际提交后才创建 View。导航取消、失败或渲染未提交时不会产生无效 View;发生成功
重定向时,View 使用最终提交的 pathname。
App Router:Next.js 13 至 15.2¶
这些版本没有 instrumentation-client,可以在根 layout 中放置一个客户端
初始化组件:
// app/rum-provider.tsx
"use client"
import { useEffect } from "react"
import { datafluxRum } from "@cloudcare/browser-rum"
import {
nextjsPlugin,
RumNextjsAppRouter,
} from "@cloudcare/browser-rum-nextjs"
let initialized = false
export function RumProvider() {
useEffect(() => {
if (initialized) return
initialized = true
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nextjs",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [nextjsPlugin()],
})
}, [])
return <RumNextjsAppRouter />
}
在 app/layout.tsx 中渲染 <RumProvider />。这种方式能够采集已成功提交的
App Router 路由,但初始化时机晚于 instrumentation-client。
Pages Router¶
在 pages/_app.tsx 中初始化并渲染 Pages Router tracker:
import { useEffect } from "react"
import { datafluxRum } from "@cloudcare/browser-rum"
import {
nextjsPlugin,
RumNextjsPagesRouter,
} from "@cloudcare/browser-rum-nextjs"
let initialized = false
export default function App({ Component, pageProps }) {
useEffect(() => {
if (initialized) return
initialized = true
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nextjs",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [nextjsPlugin()],
})
}, [])
return (
<>
<RumNextjsPagesRouter />
<Component {...pageProps} />
</>
)
}
Pages Router 使用 router.pathname 作为模板名称,例如实际 URL
/users/42 会归入 /users/[id]。routeChangeError、取消导航以及仅 query
或 hash 变化不会创建新 View。
Next.js View 与 Error¶
App Router 根据 usePathname() 和 useParams() 生成文件路由模板:
| 实际 URL | View 名称 |
|---|---|
/ |
/ |
/users/42 |
/users/[id] |
/docs/a/b |
/docs/[...slug] |
无法自动生成稳定名称时,可以传入 getViewName:
在 App Router 的 error.tsx、global-error.tsx 或业务错误处理器中调用
addNextjsError():
"use client"
import { useEffect } from "react"
import { addNextjsError } from "@cloudcare/browser-rum-nextjs"
export default function ErrorPage({ error, reset }) {
useEffect(() => {
addNextjsError(error, undefined, {
route_boundary: "dashboard",
})
}, [error])
return <button onClick={reset}>重试</button>
}
错误对象包含 Next.js digest 时,插件会把它写入 Error 上下文,便于关联
服务端日志。插件还提供 ErrorBoundary,可用于保护客户端 React 子树。
Nuxt¶
Nuxt 插件支持 Nuxt 3、4,以及 Vue 3 和 Vue Router 4。
安装¶
创建客户端插件¶
在项目 plugins 目录中创建 rum.client.ts。.client 后缀确保代码只在浏览器
运行,enforce: "pre" 让 RUM 尽早安装路由和错误监听。
import { datafluxRum } from "@cloudcare/browser-rum"
import { nuxtRumPlugin } from "@cloudcare/browser-rum-nuxt"
export default defineNuxtPlugin({
name: "dataflux-rum",
enforce: "pre",
setup(nuxtApp) {
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nuxt",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [
nuxtRumPlugin({
nuxtApp,
router: useRouter(),
}),
],
})
},
})
Nuxt 会自动注册 plugins 目录顶层的插件,不需要再写入 nuxt.config.ts。
同一应用不要同时使用 Nuxt 插件和 Vue 插件跟踪同一个 Router。
Nuxt View 与 Error¶
插件将 Vue Router 参数路径转换为 Nuxt 文件路由名称:
| Vue Router 路径 | RUM View 名称 |
|---|---|
/users/:id |
/users/[id] |
/users/:id? |
/users/[[id]] |
/docs/:slug(.*)* |
/docs/[...slug] |
成功的 pathname 导航和 hash 路由会创建 View;仅 query 变化和失败导航不会创建
View。需要自定义名称时,在 nuxtRumPlugin() 中传入
getViewName(route)。
传入 nuxtApp 后,插件同时处理 Vue 组件错误和 Nuxt app:error。同一个 Error
对象在一次传播中同时进入两条错误链路时只会上报一次,并保留应用已有的 Vue
错误处理器。
业务主动捕获错误时调用 addNuxtError():
import { addNuxtError } from "@cloudcare/browser-rum-nuxt"
try {
await submitOrder()
} catch (error) {
addNuxtError(error, {
operation: "submit_order",
module: "checkout",
})
}
验证接入¶
- 打开浏览器开发者工具,在 Network 中过滤
/v1/write/rum。 - 首次进入页面,确认出现
type=view。 - 进入动态路由,确认 View 使用
/users/[id]等文件路由模板。 - 只修改 query,确认没有重复创建 View。
- 触发客户端组件错误,确认出现
type=error,并包含context.framework = nextjs或context.framework = nuxt。
常见问题¶
构建时报 window is not defined¶
RUM 初始化进入了服务端模块。Next.js 应使用 instrumentation-client.ts 或带
"use client" 的初始化组件;Nuxt 插件文件必须使用 .client.ts 或
.client.js 后缀。
有 Error 但没有框架 View¶
Next.js 必须渲染与当前 Router 对应的 tracker;Nuxt 插件必须传入
router: useRouter()。同一个应用不要混用多个 Router tracker。
一个跳转产生多个 View¶
整个应用只放置一个 tracker,也不要再为同一次导航调用
datafluxRum.startView()。