跳转至

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 的 siteclientToken。使用 DataKit 直连时, 将这两个参数替换为 datakitOrigin,不要同时配置两种上报地址。

Next.js

Next.js 插件支持 Next.js 13 及以上、React 18 及以上,以及 App Router 和 Pages Router。

安装

npm install @cloudcare/browser-rum @cloudcare/browser-rum-nextjs

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

<RumNextjsAppRouter
  getViewName={(pathname, params) => (
    params.id ? "/users/[id]" : pathname
  )}
/>

在 App Router 的 error.tsxglobal-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。

安装

npm install @cloudcare/browser-rum @cloudcare/browser-rum-nuxt

创建客户端插件

在项目 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",
  })
}

验证接入

  1. 打开浏览器开发者工具,在 Network 中过滤 /v1/write/rum
  2. 首次进入页面,确认出现 type=view
  3. 进入动态路由,确认 View 使用 /users/[id] 等文件路由模板。
  4. 只修改 query,确认没有重复创建 View。
  5. 触发客户端组件错误,确认出现 type=error,并包含 context.framework = nextjscontext.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()

文档评价

文档内容是否对您有帮助?