Next.js性能监控 #
一、Web Vitals #
1.1 核心指标 #
| 指标 | 说明 | 目标值 |
|---|---|---|
| LCP | 最大内容绘制 | < 2.5s |
| FID | 首次输入延迟 | < 100ms |
| CLS | 累积布局偏移 | < 0.1 |
| TTFB | 首字节时间 | < 600ms |
| INP | 交互到下一次绘制 | < 200ms |
1.2 测量Web Vitals #
tsx
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
console.log(metric)
})
return null
}
1.3 发送到分析服务 #
tsx
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
const body = JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
})
fetch('/api/analytics', {
body,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
})
})
return null
}
1.4 在布局中使用 #
tsx
import { WebVitals } from './WebVitals'
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<WebVitals />
</body>
</html>
)
}
二、自定义指标 #
2.1 使用performance API #
tsx
'use client'
import { useEffect } from 'react'
export function measurePerformance() {
useEffect(() => {
const startTime = performance.now()
return () => {
const endTime = performance.now()
console.log(`Component rendered in ${endTime - startTime}ms`)
}
}, [])
}
2.2 自定义标记 #
tsx
'use client'
export function trackEvent(name: string, data?: Record<string, any>) {
performance.mark(name)
if (typeof window !== 'undefined' && window.gtag) {
window.gtag('event', name, data)
}
}
2.3 性能观察者 #
tsx
'use client'
import { useEffect } from 'react'
export function PerformanceObserver() {
useEffect(() => {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.duration)
}
})
observer.observe({ entryTypes: ['measure', 'navigation'] })
return () => observer.disconnect()
}, [])
return null
}
三、错误追踪 #
3.1 全局错误处理 #
tsx
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error
reset: () => void
}) {
useEffect(() => {
reportError(error)
}, [error])
return (
<html>
<body>
<h2>出错了!</h2>
<button onClick={reset}>重试</button>
</body>
</html>
)
}
3.2 错误上报 #
tsx
function reportError(error: Error) {
fetch('/api/errors', {
method: 'POST',
body: JSON.stringify({
message: error.message,
stack: error.stack,
url: window.location.href,
timestamp: new Date().toISOString(),
}),
})
}
3.3 Sentry集成 #
tsx
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 1,
})
四、日志 #
4.1 服务端日志 #
tsx
import { NextRequest, NextResponse } from 'next/server'
export async function middleware(request: NextRequest) {
const start = Date.now()
const response = NextResponse.next()
const duration = Date.now() - start
console.log({
method: request.method,
url: request.url,
status: response.status,
duration: `${duration}ms`,
})
return response
}
4.2 结构化日志 #
tsx
interface LogEntry {
level: 'info' | 'warn' | 'error'
message: string
timestamp: string
context?: Record<string, any>
}
function log(entry: LogEntry) {
console.log(JSON.stringify(entry))
}
log({
level: 'info',
message: 'Request processed',
timestamp: new Date().toISOString(),
context: { path: '/api/users', method: 'GET' },
})
4.3 API日志 #
tsx
import { NextRequest, NextResponse } from 'next/server'
export async function GET(request: NextRequest) {
const start = Date.now()
try {
const data = await getData()
console.log({
type: 'api_request',
method: 'GET',
path: '/api/data',
status: 200,
duration: Date.now() - start,
})
return NextResponse.json(data)
} catch (error) {
console.error({
type: 'api_error',
method: 'GET',
path: '/api/data',
error: error.message,
duration: Date.now() - start,
})
return NextResponse.json({ error: 'Internal Error' }, { status: 500 })
}
}
五、性能分析 #
5.1 React DevTools Profiler #
tsx
import { Profiler } from 'react'
function onRenderCallback(
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime
) {
console.log({
id,
phase,
actualDuration,
baseDuration,
})
}
export default function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<Component />
</Profiler>
)
}
5.2 Next.js分析 #
bash
ANALYZE=true npm run build
typescript
import type { NextConfig } from 'next'
import bundleAnalyzer from '@next/bundle-analyzer'
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
})
const nextConfig: NextConfig = {}
export default withBundleAnalyzer(nextConfig)
5.3 Chrome DevTools #
- Performance面板
- Network面板
- Lighthouse
六、监控服务 #
6.1 Vercel Analytics #
tsx
import { Analytics } from '@vercel/analytics/react'
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
</body>
</html>
)
}
6.2 Google Analytics #
tsx
import Script from 'next/script'
export default function RootLayout({ children }) {
return (
<html>
<head>
<Script
src="https://www.googletagmanager.com/gtag/js?id=GA_ID"
strategy="afterInteractive"
/>
</head>
<body>{children}</body>
</html>
)
}
七、最佳实践 #
7.1 监控关键指标 #
- LCP、FID、CLS
- API响应时间
- 错误率
7.2 设置告警 #
- 性能下降告警
- 错误率告警
- 可用性告警
7.3 定期审查 #
- 每周检查性能报告
- 分析慢请求
- 优化瓶颈
八、总结 #
性能监控要点:
| 要点 | 说明 |
|---|---|
| Web Vitals | 核心指标 |
| 自定义指标 | 业务指标 |
| 错误追踪 | Sentry |
| 日志 | 结构化日志 |
| 分析工具 | Bundle Analyzer |
下一步,让我们学习最佳实践!
最后更新:2026-03-28