Skip to content

Commit

Permalink
Send web vitals to Vercel analytics in app (#40669)
Browse files Browse the repository at this point in the history
Sends web vitals to Vercel analytics.

My plan for the test was to assert the data sent by the client but there's a bug where it's always null when sending a blob microsoft/playwright#6479.

When adding support for a custom web vitals reporter it will be easier to assert the values sent by the reporter.
  • Loading branch information
Hannes Bornö committed Sep 19, 2022
1 parent d41ca43 commit 356b6ce
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
6 changes: 6 additions & 0 deletions packages/next/client/app-index.tsx
Expand Up @@ -5,6 +5,8 @@ import ReactDOMClient from 'react-dom/client'
import React from 'react'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack'

import measureWebVitals from './performance-relayer'

/// <reference types="react-dom/experimental" />

// Override chunk URL mapping in the webpack runtime
Expand Down Expand Up @@ -151,6 +153,10 @@ function ServerRoot({ cacheKey }: { cacheKey: string }) {
}

function Root({ children }: React.PropsWithChildren<{}>): React.ReactElement {
React.useEffect(() => {
measureWebVitals()
}, [])

if (process.env.__NEXT_TEST_MODE) {
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/next/client/performance-relayer.ts
Expand Up @@ -32,7 +32,7 @@ function onReport(metric: Metric): void {
const body: Record<string, string> = {
dsn: process.env.__NEXT_ANALYTICS_ID,
id: metric.id,
page: window.__NEXT_DATA__.page,
page: window.__NEXT_DATA__?.page,
href: initialHref,
event_name: metric.name,
value: metric.value.toString(),
Expand Down
37 changes: 37 additions & 0 deletions test/e2e/app-dir/index.test.ts
Expand Up @@ -29,6 +29,9 @@ describe('app dir', () => {
'react-dom': 'experimental',
},
skipStart: true,
env: {
VERCEL_ANALYTICS_ID: 'fake-analytics-id',
},
})

if (assetPrefix) {
Expand Down Expand Up @@ -1454,6 +1457,40 @@ describe('app dir', () => {
})
})

// Analytics events are only sent in production
;(isDev ? describe.skip : describe)('Vercel analytics', () => {
it('should send web vitals to Vercel analytics', async () => {
let eventsCount = 0
let countEvents = false
const browser = await webdriver(next.url, '/client-nested', {
beforePageLoad(page) {
page.route(
'https://vitals.vercel-insights.com/v1/vitals',
(route) => {
if (countEvents) {
eventsCount += 1
}

route.fulfill()
}
)
},
})

// Start counting analytics events
countEvents = true

// Refresh will trigger CLS and LCP. When page loads FCP and TTFB will trigger:
await browser.refresh()

// After interaction LCP and FID will trigger
await browser.elementByCss('button').click()

// Make sure all registered events in performance-relayer has fired
await check(() => eventsCount, /6/)
})
})

describe('known bugs', () => {
it('should not share flight data between requests', async () => {
const fetches = await Promise.all(
Expand Down

0 comments on commit 356b6ce

Please sign in to comment.