Vue 3 项目跑起来之后,性能问题往往不是开发阶段能暴露的:本地一切流畅,上了生产环境,某些地区用户首屏要五六秒,某个接口偶发超时,客服反馈来了但复现不了。这类问题的根源在于缺少线上真实用户环境的数据采集,也就是通常说的 RUM(Real User Monitoring)。New Relic 的 Browser 监控正是做这件事的,它能在真实用户浏览器里采集页面加载、路由切换、接口请求耗时和 JavaScript 错误,并把数据汇总成可分析的面板。这篇文章就来聊聊在 Vue 3 工程化项目中,从接入、配置到自定义埋点的完整实践。

一、接入方式的选择:copy-paste 还是 npm 包
New Relic Browser 提供两种接入方式。第一种是 copy-paste 方式,直接在 index.html 的 <head> 里贴一段带 loader 脚本的片段,优点是不依赖构建工具,几分钟就能跑通;缺点是脚本地址写死在 HTML 里,不同环境(测试、预发、生产)需要手动维护多份模板,容易漏改。
第二种是 npm 方式,安装 @newrelic/browser-agent 后在应用入口初始化,配置项可以用环境变量驱动,天然契合 Vue CLI 或 Vite 的多环境构建。对于 Vue 3 工程化项目,我更推荐这种方式,因为初始化时机完全由代码控制,还能结合路由钩子做更精细的上报。
npm 接入的核心代码如下,放在 main.ts 的最顶部,确保在任何业务代码执行前完成初始化:
import { BrowserAgent } from '@newrelic/browser-agent/loaders/browser-agent'
const options = {
init: {
distributed_tracing: { enabled: true },
privacy: { cookies_enabled: true },
ajax: { deny_list: [] }
},
info: { beacon: '', applicationID: '你的应用ID', licenseKey: '你的LicenseKey' },
loader_config: {
accountID: '你的账户ID',
trustKey: '你的账户ID',
agentID: '你的应用ID',
licenseKey: '你的LicenseKey',
applicationID: '你的应用ID'
}
}
if (import.meta.env.PROD) {
// 只在生产环境启用,避免开发环境的噪音数据
const agent = new BrowserAgent(options)
window.__nrAgent = agent
}注意这里用 import.meta.env.PROD 做了环境判断。开发环境如果也开着采集,本地的热更新请求、mock 接口都会混进面板,数据基本没法看。License Key 这类敏感信息建议放在 .env.production 文件里,通过 import.meta.env.VITE_NR_LICENSE 读取,避免硬编码进仓库。
二、路由切换与接口耗时的采集
Vue 3 是单页应用,默认的 PageView 事件只在首次加载时触发一次,后续的路由切换 New Relic 是感知不到的。如果不做处理,面板里的页面加载数据会严重失真——你会看到几乎所有会话都只有一次 PV。解决办法是借助 singlePageApp 配置或者手动在路由钩子里触发 noticeError 与自定义事件。
新版 browser-agent 已经内置了对 SPA 的支持,初始化时开启即可:
const options = {
init: {
distributed_tracing: { enabled: true },
ajax: { deny_list: ['baidu.com', 'example.cn'] },
spa: { enabled: true } // 开启单页应用支持,自动监听 history 路由变化
},
// 其余配置同上
}开启之后,agent 会自动 hook history.pushState 和 replaceState,每次路由切换都会生成一次新的 PageView 时机统计。如果你的项目用的是 hash 模式路由,需要确认 agent 版本在 1.221 以上,早期版本对 hash 路由的支持不完整。
接口耗时方面,agent 默认会自动采集 XMLHttpRequest 和 fetch 请求,包括耗时、状态码和请求地址。但有几点要处理:第一,把第三方统计、地图 SDK 这类与业务无关的域名加进 deny_list,否则会稀释平均耗时数据;第二,对于带 token 的接口地址,注意 URL 中的查询参数是否包含敏感信息,可以通过 url`
`: 相关配置做脱敏处理。
三、错误采集与 Source Map 还原
Vue 3 的组件错误默认会被 Vue 自身的错误处理机制捕获,不一定能冒泡到 window 的 error 事件,所以仅靠 agent 的自动采集可能漏报。稳妥的做法是在 app.config.errorHandler 里主动调用 newrelic.noticeError:
import app from './main'
app.config.errorHandler = (err, instance, info) => {
// err 是错误对象,info 是 Vue 内部的错误来源描述
if (window.newrelic) {
window.newrelic.noticeError(err, { component: instance?.$options?.name, info })
}
console.error(err)
}
// 捕获 Promise 未处理的拒绝
window.addEventListener('unhandledrejection', (event) => {
if (window.newrelic) {
window.newrelic.noticeError(event.reason, { type: 'unhandledrejection' })
}
})第二个关键问题是 Source Map。生产构建的代码经过压缩混淆,堆栈里的报错位置是一行 min.js 里的行列号,根本定位不到源码。New Relic 支持上传 Source Map 自动还原堆栈,以 Vite 为例,构建时开启 sourcemap 输出,再通过 API 上传:
# 构建时生成 sourcemap vite build --sourcemap # 上传 sourcemap 到 New Relic(在 CI 脚本中执行) curl -X POST https://sourcemap-service.nr1-data.com/v2/applications/YOUR_APP_ID/sourcemaps \ -H "Api-Key: 你的NRAK密钥" \ -F "sourcemap=@dist/assets/index-abc123.js.map" \ -F "javascriptUrl=https://你的域名/assets/index-abc123.js"
有一个细节容易被忽略:上传时要确保 javascriptUrl 与线上实际加载的 JS 地址完全一致,包括 hash 文件名。建议把上传步骤写进 CI 流水线,在构建产物生成后立即执行,避免手动上传遗漏。同时记得在 nginx 配置里屏蔽 .map 文件的对外访问,只上传不给下载。
四、自定义指标与采样策略
自动采集覆盖的是通用指标,业务层面的性能关注点往往需要自定义。比如一个数据大屏页面,你关心的是图表数据全部渲染完成的时刻,而不是 DOM 加载完成。这时可以用 addPageAction 上报自定义事件:
// 记录关键业务节点耗时
const startTime = performance.now()
async function loadDashboard() {
await fetchAllData()
renderCharts()
window.newrelic?.addPageAction('dashboardReady', {
duration: Math.round(performance.now() - startTime),
chartCount: chartList.length
})
}上报的数据可以在 New Relic 的 Query Builder 里用类似 SELECT average(duration) FROM dashboardReady SINCE 1 day ago 的 NRQL 语句查询,还能直接生成趋势图挂到自定义面板上。
最后是采样与成本控制。Browser 盙控按月活用户计费,如果流量很大,全量采样的账单会很可观。可以从前端做采样,比如只对百分之二十的用户初始化 agent:
const sampleRate = 0.2
const shouldInit = Math.random() < sampleRate
if (import.meta.env.PROD && shouldInit) {
new BrowserAgent(options)
}更推荐的做法是用用户 ID 做一致性哈希采样,保证同一个用户每次访问的行为要么全被采集要么全不采集,这样会话级别的漏斗分析才准确。此外,结合分布式追踪开启后,前端发起的请求会携带 trace 头,后端如果也部署了 APM,就能在 New Relic 的 Distributed Tracing 页面里看到一次请求从前端点击到后端 SQL 的完整链路,排查接口慢的问题时效率会高很多。
整体来说,Vue 3 项目接入 New Relic 的核心工作集中在三块:入口初始化与环境隔离、SPA 路由与错误采集的补齐、Source Map 与自定义事件的配套。把这些做扎实,线上性能问题就从"猜"变成了"查",首屏慢在哪、哪个接口拖了后腿、哪段代码抛错最多,面板上一目了然。