Skip to content

Commit

Permalink
Move isInvalidTimestamp into getNavigationEntry
Browse files Browse the repository at this point in the history
  • Loading branch information
philipwalton committed May 3, 2024
1 parent 6fa9082 commit da7bd49
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 34 deletions.
22 changes: 9 additions & 13 deletions src/attribution/onFCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import {getBFCacheRestoreTime} from '../lib/bfcache.js';
import {getLoadState} from '../lib/getLoadState.js';
import {getNavigationEntry} from '../lib/getNavigationEntry.js';
import {isInvalidTimestamp} from '../lib/isInvalidTimestamp.js';
import {onFCP as unattributedOnFCP} from '../onFCP.js';
import {
FCPAttribution,
Expand All @@ -39,19 +38,16 @@ const attributeFCP = (metric: FCPMetric): FCPMetricWithAttribution => {
const fcpEntry = metric.entries[metric.entries.length - 1];

if (navigationEntry) {
const responseStart = navigationEntry.responseStart;
if (!isInvalidTimestamp(responseStart)) {
const activationStart = navigationEntry.activationStart || 0;
const ttfb = Math.max(0, responseStart - activationStart);
const activationStart = navigationEntry.activationStart || 0;
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);

attribution = {
timeToFirstByte: ttfb,
firstByteToFCP: metric.value - ttfb,
loadState: getLoadState(metric.entries[0].startTime),
navigationEntry,
fcpEntry,
};
}
attribution = {
timeToFirstByte: ttfb,
firstByteToFCP: metric.value - ttfb,
loadState: getLoadState(metric.entries[0].startTime),
navigationEntry,
fcpEntry,
};
}
}

Expand Down
10 changes: 4 additions & 6 deletions src/attribution/onLCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import {getNavigationEntry} from '../lib/getNavigationEntry.js';
import {getSelector} from '../lib/getSelector.js';
import {isInvalidTimestamp} from '../lib/isInvalidTimestamp.js';
import {onLCP as unattributedOnLCP} from '../onLCP.js';
import {
LCPAttribution,
Expand All @@ -34,10 +33,9 @@ const attributeLCP = (metric: LCPMetric): LCPMetricWithAttribution => {
elementRenderDelay: metric.value,
};

const navigationEntry = getNavigationEntry();
if (metric.entries.length && navigationEntry) {
const responseStart = navigationEntry.responseStart;
if (!isInvalidTimestamp(responseStart)) {
if (metric.entries.length) {
const navigationEntry = getNavigationEntry();
if (navigationEntry) {
const activationStart = navigationEntry.activationStart || 0;
const lcpEntry = metric.entries[metric.entries.length - 1];
const lcpResourceEntry =
Expand All @@ -46,7 +44,7 @@ const attributeLCP = (metric: LCPMetric): LCPMetricWithAttribution => {
.getEntriesByType('resource')
.filter((e) => e.name === lcpEntry.url)[0];

const ttfb = Math.max(0, responseStart - activationStart);
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);

const lcpRequestStart = Math.max(
ttfb,
Expand Down
24 changes: 18 additions & 6 deletions src/lib/getNavigationEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@
* limitations under the License.
*/

export const getNavigationEntry = ():
| PerformanceNavigationTiming
| undefined => {
return (
export const getNavigationEntry = (): PerformanceNavigationTiming | void => {
const navigationEntry =
self.performance &&
performance.getEntriesByType &&
performance.getEntriesByType('navigation')[0]
);
performance.getEntriesByType('navigation')[0];

// Check to ensure the `responseStart` property is present and valid.
// In some cases no value is reported by the browser (for
// privacy/security reasons), and in other cases (bugs) the value is
// negative or is larger than the current page time. Ignore these cases:
// https://github.com/GoogleChrome/web-vitals/issues/137
// https://github.com/GoogleChrome/web-vitals/issues/162
// https://github.com/GoogleChrome/web-vitals/issues/275
if (
navigationEntry &&
navigationEntry.responseStart > 0 &&
navigationEntry.responseStart < performance.now()
) {
return navigationEntry;
}
};
16 changes: 7 additions & 9 deletions src/onTTFB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import {bindReporter} from './lib/bindReporter.js';
import {initMetric} from './lib/initMetric.js';
import {isInvalidTimestamp} from './lib/isInvalidTimestamp.js';
import {onBFCacheRestore} from './lib/bfcache.js';
import {getNavigationEntry} from './lib/getNavigationEntry.js';
import {MetricRatingThresholds, ReportOpts, TTFBMetric} from './types.js';
Expand Down Expand Up @@ -72,20 +71,19 @@ export const onTTFB = (
);

whenReady(() => {
const navEntry = getNavigationEntry();

if (navEntry) {
const responseStart = navEntry.responseStart;

if (isInvalidTimestamp(responseStart)) return;
const navigationEntry = getNavigationEntry();

if (navigationEntry) {
// The activationStart reference is used because TTFB should be
// relative to page activation rather than navigation start if the
// page was prerendered. But in cases where `activationStart` occurs
// after the first byte is received, this time should be clamped at 0.
metric.value = Math.max(responseStart - getActivationStart(), 0);
metric.value = Math.max(
navigationEntry.responseStart - getActivationStart(),
0,
);

metric.entries = [navEntry];
metric.entries = [navigationEntry];
report(true);

// Only report TTFB after bfcache restores if a `navigation` entry
Expand Down

0 comments on commit da7bd49

Please sign in to comment.