0
# Additional Web Vitals
1
2
Measurement functions for additional Web Vitals metrics that are useful for performance monitoring and debugging: First Contentful Paint (FCP) and Time to First Byte (TTFB).
3
4
## Capabilities
5
6
### First Contentful Paint (FCP)
7
8
Measures the [FCP](https://web.dev/articles/fcp) value for the current page and calls the callback function once the value is ready. FCP measures loading performance by identifying when the first text or image content becomes visible to users.
9
10
```typescript { .api }
11
/**
12
* Calculates the FCP value and calls callback with paint timing data
13
* @param callback - Function to receive FCP metric data
14
* @param opts - Optional configuration for reporting behavior
15
*/
16
function onFCP(callback: (metric: FCPMetric) => void, opts?: ReportOpts): void;
17
18
interface FCPMetric extends Metric {
19
name: 'FCP';
20
entries: PerformancePaintTiming[];
21
}
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { onFCP } from "web-vitals";
28
29
// Track FCP timing
30
onFCP((metric) => {
31
console.log('FCP time:', metric.value + 'ms');
32
console.log('Rating:', metric.rating);
33
34
const paintEntry = metric.entries[0];
35
console.log('Paint entry name:', paintEntry.name); // 'first-contentful-paint'
36
console.log('Start time:', paintEntry.startTime);
37
});
38
39
// Send FCP data to analytics
40
onFCP((metric) => {
41
gtag('event', 'web_vitals', {
42
event_category: 'Performance',
43
event_label: 'FCP',
44
value: Math.round(metric.value),
45
custom_map: { metric_rating: metric.rating }
46
});
47
});
48
```
49
50
**Important Notes:**
51
- Reports once when first contentful paint occurs
52
- Uses Paint Timing API with `first-contentful-paint` entry
53
- Represents when users see first meaningful content
54
- Threshold: ≤1.8s (good), 1.8-3s (needs improvement), >3s (poor)
55
56
### Time to First Byte (TTFB)
57
58
Measures the [TTFB](https://web.dev/articles/ttfb) value for the current page and calls the callback function once the page has loaded. TTFB measures the time from navigation start to when the first byte of the response is received.
59
60
```typescript { .api }
61
/**
62
* Calculates the TTFB value and calls callback with navigation timing data
63
* @param callback - Function to receive TTFB metric data
64
* @param opts - Optional configuration for reporting behavior
65
*/
66
function onTTFB(callback: (metric: TTFBMetric) => void, opts?: ReportOpts): void;
67
68
interface TTFBMetric extends Metric {
69
name: 'TTFB';
70
entries: PerformanceNavigationTiming[];
71
}
72
```
73
74
**Usage Examples:**
75
76
```typescript
77
import { onTTFB } from "web-vitals";
78
79
// Track TTFB timing
80
onTTFB((metric) => {
81
console.log('TTFB time:', metric.value + 'ms');
82
console.log('Rating:', metric.rating);
83
84
const navEntry = metric.entries[0];
85
console.log('DNS lookup time:', navEntry.domainLookupEnd - navEntry.domainLookupStart);
86
console.log('Connection time:', navEntry.connectEnd - navEntry.connectStart);
87
console.log('Request time:', metric.value - navEntry.requestStart);
88
});
89
90
// Break down server response time components
91
onTTFB((metric) => {
92
const navEntry = metric.entries[0];
93
94
// Calculate sub-timings
95
const dnsTime = navEntry.domainLookupEnd - navEntry.domainLookupStart;
96
const connectionTime = navEntry.connectEnd - navEntry.connectStart;
97
const requestTime = metric.value - navEntry.requestStart;
98
99
console.log('Network breakdown:', {
100
dns: dnsTime,
101
connection: connectionTime,
102
serverResponse: requestTime,
103
total: metric.value
104
});
105
});
106
```
107
108
**Important Notes:**
109
- Waits until page load to ensure all navigation timing properties are available
110
- Includes time from navigation start to first response byte
111
- Encompasses DNS lookup, connection, and server processing time
112
- Fallback to `performance.timing` for older browsers
113
- Threshold: ≤800ms (good), 800-1800ms (needs improvement), >1800ms (poor)
114
115
## Performance Entry Types
116
117
The Additional Web Vitals metrics use specific performance entry types:
118
119
```typescript { .api }
120
/** Paint timing entries for FCP measurement */
121
interface PerformancePaintTiming extends PerformanceEntry {
122
/** For FCP, this will be 'first-contentful-paint' */
123
name: string;
124
/** Timestamp when the paint occurred */
125
startTime: DOMHighResTimeStamp;
126
}
127
128
/** Navigation timing entries for TTFB measurement */
129
interface PerformanceNavigationTiming extends PerformanceEntry {
130
/** Start of DNS lookup */
131
domainLookupStart: DOMHighResTimeStamp;
132
/** End of DNS lookup */
133
domainLookupEnd: DOMHighResTimeStamp;
134
/** Start of TCP connection */
135
connectStart: DOMHighResTimeStamp;
136
/** End of TCP connection */
137
connectEnd: DOMHighResTimeStamp;
138
/** Start of request */
139
requestStart: DOMHighResTimeStamp;
140
/** Start of response (TTFB) */
141
responseStart: DOMHighResTimeStamp;
142
/** End of response */
143
responseEnd: DOMHighResTimeStamp;
144
/** Activation start for prerendered pages */
145
activationStart?: DOMHighResTimeStamp;
146
}
147
```
148
149
## Usage Patterns
150
151
### Combining with Core Web Vitals
152
153
```typescript
154
import { onFCP, onLCP, onCLS, onINP, onTTFB } from "web-vitals";
155
156
// Comprehensive performance monitoring
157
const performanceData = {
158
fcp: null,
159
lcp: null,
160
cls: null,
161
inp: null,
162
ttfb: null
163
};
164
165
onFCP((metric) => performanceData.fcp = metric);
166
onLCP((metric) => performanceData.lcp = metric);
167
onCLS((metric) => performanceData.cls = metric);
168
onINP((metric) => performanceData.inp = metric);
169
onTTFB((metric) => performanceData.ttfb = metric);
170
171
// Send comprehensive report when page becomes hidden
172
document.addEventListener('visibilitychange', () => {
173
if (document.visibilityState === 'hidden') {
174
sendAnalytics(performanceData);
175
}
176
});
177
```
178
179
### Loading Performance Analysis
180
181
```typescript
182
import { onFCP, onLCP, onTTFB } from "web-vitals";
183
184
// Analyze loading performance stages
185
onTTFB((metric) => {
186
console.log('Server response time:', metric.value + 'ms');
187
});
188
189
onFCP((metric) => {
190
console.log('First content visible:', metric.value + 'ms');
191
});
192
193
onLCP((metric) => {
194
console.log('Main content loaded:', metric.value + 'ms');
195
});
196
```