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