Skip to content

Commit

Permalink
PR cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
mklocke-shopify committed May 3, 2023
1 parent 42b7dd3 commit a096449
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changeset/kind-pens-knock.md
@@ -0,0 +1,6 @@
---
'@shopify/koa-performance': patch
'@shopify/performance': patch
---

Added support for Cumulative Layout Shift in the performance and koa-performance packages.
1 change: 1 addition & 0 deletions packages/koa-performance/src/enums.ts
Expand Up @@ -5,6 +5,7 @@ export enum LifecycleMetric {
TimeToFirstPaint = 'time_to_first_paint',
DomContentLoaded = 'dom_content_loaded',
FirstInputDelay = 'first_input_delay',
CumulativeLayoutShift = 'cumulative_layout_shift',
Load = 'dom_load',
}

Expand Down
7 changes: 6 additions & 1 deletion packages/koa-performance/src/middleware.ts
Expand Up @@ -121,11 +121,15 @@ export function clientPerformanceMetrics({
tags,
});
}
const value =
let value =
event.type === EventType.FirstInputDelay
? event.duration
: event.start;

// For CLS we multiply the value by 100 to avoid statsd issues with real numbers.
value =
event.type === EventType.CumulativeLayoutShift ? value * 100 : value;

metrics.push({
name: eventMetricName(event),
value: Math.round(value),
Expand Down Expand Up @@ -261,6 +265,7 @@ const EVENT_METRIC_MAPPING = {
[EventType.TimeToFirstPaint]: LifecycleMetric.TimeToFirstPaint,
[EventType.DomContentLoaded]: LifecycleMetric.DomContentLoaded,
[EventType.FirstInputDelay]: LifecycleMetric.FirstInputDelay,
[EventType.CumulativeLayoutShift]: LifecycleMetric.CumulativeLayoutShift,
[EventType.Load]: LifecycleMetric.Load,
};

Expand Down
15 changes: 14 additions & 1 deletion packages/koa-performance/src/tests/middleware.test.ts
Expand Up @@ -240,10 +240,15 @@ describe('client metrics middleware', () => {
456,
);

const clsEvent = createLifecycleEvent(
EventType.CumulativeLayoutShift,
0.1,
);

const context = createMockContext({
method: Method.Post,
requestBody: createBody({
events: [ttfbEvent, ttfcpEvent, ttlcpEvent],
events: [ttfbEvent, ttfcpEvent, ttlcpEvent, clsEvent],
}),
});

Expand All @@ -253,6 +258,8 @@ describe('client metrics middleware', () => {
);
});

expect(statsd.distribution).toHaveBeenCalledTimes(4);

expect(statsd.distribution).toHaveBeenCalledWith(
'time_to_first_byte',
ttfbEvent.start,
Expand All @@ -270,6 +277,12 @@ describe('client metrics middleware', () => {
ttlcpEvent.start,
expect.any(Object),
);

expect(statsd.distribution).toHaveBeenCalledWith(
'cumulative_layout_shift',
clsEvent.start * 100,
expect.any(Object),
);
});

it('sends distribution for redirect_duration when ttfb is supplied with relevant metadata', async () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/performance/README.md
Expand Up @@ -135,6 +135,11 @@ Learn more about [DOM Content Loaded](https://developer.mozilla.org/en-US/docs/W
The time from when a user first interacts with your site to the time when the browser is able to respond to that interaction.
Learn more about [first Input Delay](https://developers.google.com/web/updates/2018/05/first-input-delay).

##### Cumulative Layout Shift (`EventType.CumulativeLayoutShift`)

CLS is a measure of the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifespan of a page.
Learn more about [Cumulative Layout Shift](https://web.dev/cls/)

##### Load Event (`EventType.Load`)

The time until the DOM and all its styles and synchronous scripts have loaded.
Expand Down
16 changes: 12 additions & 4 deletions packages/performance/src/performance.ts
@@ -1,15 +1,15 @@
import {onLCP, onFID, onFCP, onTTFB} from 'web-vitals';
import {onCLS, onFCP, onFID, onLCP, onTTFB} from 'web-vitals';

import {InflightNavigation} from './inflight';
import type {Navigation} from './navigation';
import {
hasGlobal,
now,
referenceTime,
supportsPerformanceObserver,
withEntriesOfType,
withNavigation,
withTiming,
supportsPerformanceObserver,
referenceTime,
hasGlobal,
getResourceTypeFromEntry,
} from './utilities';
import type {Event, LifecycleEvent} from './types';
Expand Down Expand Up @@ -174,6 +174,14 @@ export class Performance {
});
});

onCLS((metric) => {
this.lifecycleEvent({
type: EventType.CumulativeLayoutShift,
start: metric.value,
duration: 0,
});
});

onLCP((metric) => {
this.lifecycleEvent({
type: EventType.TimeToLargestContentfulPaint,
Expand Down
8 changes: 8 additions & 0 deletions packages/performance/src/types.ts
Expand Up @@ -5,6 +5,7 @@ export enum EventType {
TimeToLargestContentfulPaint = 'ttlcp',
DomContentLoaded = 'dcl',
FirstInputDelay = 'fid',
CumulativeLayoutShift = 'cls',
Load = 'load',
LongTask = 'longtask',
Usable = 'usable',
Expand Down Expand Up @@ -53,6 +54,11 @@ export interface FirstInputDelayEvent extends BasicEvent {
metadata?: undefined;
}

export interface CumulativeLayoutShift extends BasicEvent {
type: EventType.CumulativeLayoutShift;
metadata?: undefined;
}

export interface LoadEvent extends BasicEvent {
type: EventType.Load;
metadata?: undefined;
Expand Down Expand Up @@ -94,6 +100,7 @@ export type LifecycleEvent =
| TimeToLargestContentfulPaintEvent
| DomContentLoadedEvent
| FirstInputDelayEvent
| CumulativeLayoutShift
| LoadEvent;

export type Event =
Expand All @@ -112,6 +119,7 @@ export interface EventMap {
[EventType.TimeToLargestContentfulPaint]: TimeToLargestContentfulPaintEvent;
[EventType.DomContentLoaded]: DomContentLoadedEvent;
[EventType.FirstInputDelay]: FirstInputDelayEvent;
[EventType.CumulativeLayoutShift]: CumulativeLayoutShift;
[EventType.Load]: LoadEvent;
[EventType.ScriptDownload]: ScriptDownloadEvent;
[EventType.StyleDownload]: StyleDownloadEvent;
Expand Down

0 comments on commit a096449

Please sign in to comment.