auto-claude: subtask-2-3 - Add web-vitals reporting to layout for Core Web Vitals monitoring
- Create WebVitals client component in src/components/analytics/ - Track LCP, INP, CLS, FCP, and TTFB metrics - Log metrics to console in development mode - Send metrics to Google Analytics when available - Add WebVitals component to root layout Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { onCLS, onINP, onLCP, onFCP, onTTFB, type Metric } from 'web-vitals';
|
||||
|
||||
type WebVitalsReportHandler = (metric: Metric) => void;
|
||||
|
||||
interface WebVitalsProps {
|
||||
/**
|
||||
* Optional custom report handler. If not provided, metrics are logged to console in development.
|
||||
*/
|
||||
onReport?: WebVitalsReportHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports Core Web Vitals metrics.
|
||||
*
|
||||
* Metrics tracked:
|
||||
* - LCP (Largest Contentful Paint): measures loading performance
|
||||
* - INP (Interaction to Next Paint): measures interactivity
|
||||
* - CLS (Cumulative Layout Shift): measures visual stability
|
||||
* - FCP (First Contentful Paint): measures time to first content
|
||||
* - TTFB (Time to First Byte): measures server response time
|
||||
*/
|
||||
export function WebVitals({ onReport }: WebVitalsProps) {
|
||||
useEffect(() => {
|
||||
const handleMetric: WebVitalsReportHandler = (metric) => {
|
||||
if (onReport) {
|
||||
onReport(metric);
|
||||
} else if (process.env.NODE_ENV === 'development') {
|
||||
// Log metrics in development for debugging
|
||||
const { name, value, rating, id } = metric;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`[Web Vitals] ${name}: ${value.toFixed(2)} (${rating}) [${id}]`);
|
||||
}
|
||||
|
||||
// Send to Google Analytics if available
|
||||
if (typeof window !== 'undefined' && 'gtag' in window) {
|
||||
const gtag = window.gtag as (
|
||||
command: string,
|
||||
eventName: string,
|
||||
params: Record<string, unknown>
|
||||
) => void;
|
||||
|
||||
gtag('event', metric.name, {
|
||||
event_category: 'Web Vitals',
|
||||
event_label: metric.id,
|
||||
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
|
||||
non_interaction: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Register all Core Web Vitals observers
|
||||
// Each function returns an unsubscribe function, but web-vitals v5 doesn't require cleanup
|
||||
// as it uses PerformanceObserver internally which is garbage collected
|
||||
onCLS(handleMetric);
|
||||
onINP(handleMetric);
|
||||
onLCP(handleMetric);
|
||||
onFCP(handleMetric);
|
||||
onTTFB(handleMetric);
|
||||
}, [onReport]);
|
||||
|
||||
// This component doesn't render anything
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { WebVitals } from './WebVitals';
|
||||
Reference in New Issue
Block a user