Rocky_Mountain_Vending/.pnpm-store/v10/files/28/f7af47feb408863a53ce414c827864ff628a1820a3eafc753f7ec1df147432773ea8126bcac478f6b84c4dcb5758ef9e8cfa7cd5ef3e2f6f0693458396d468
DMleadgen 46d973904b
Initial commit: Rocky Mountain Vending website
Next.js website for Rocky Mountain Vending company featuring:
- Product catalog with Stripe integration
- Service areas and parts pages
- Admin dashboard with Clerk authentication
- SEO optimized pages with JSON-LD structured data

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 16:22:15 -07:00

257 lines
No EOL
12 KiB
Text

// Copyright 2024 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// import * as i18n from '../../../core/i18n/i18n.js';
import * as Helpers from '../helpers/helpers.js';
import * as Types from '../types/types.js';
import { isRequestCompressed } from './Common.js';
import { InsightCategory, InsightKeys, InsightWarning, } from './types.js';
export const UIStrings = {
/**
* @description Title of an insight that provides a breakdown for how long it took to download the main document.
*/
title: 'Document request latency',
/**
* @description Description of an insight that provides a breakdown for how long it took to download the main document.
*/
description: 'Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression.',
/**
* @description Text to tell the user that the document request does not have redirects.
*/
passingRedirects: 'Avoids redirects',
/**
* @description Text to tell the user that the document request had redirects.
* @example {3} PH1
* @example {1000 ms} PH2
*/
failedRedirects: 'Had redirects ({PH1} redirects, +{PH2})',
/**
* @description Text to tell the user that the time starting the document request to when the server started responding is acceptable.
* @example {600 ms} PH1
*/
passingServerResponseTime: 'Server responds quickly (observed {PH1})',
/**
* @description Text to tell the user that the time starting the document request to when the server started responding is not acceptable.
* @example {601 ms} PH1
*/
failedServerResponseTime: 'Server responded slowly (observed {PH1})',
/**
* @description Text to tell the user that text compression (like gzip) was applied.
*/
passingTextCompression: 'Applies text compression',
/**
* @description Text to tell the user that text compression (like gzip) was not applied.
*/
failedTextCompression: 'No compression applied',
/**
* @description Text for a label describing a network request event as having redirects.
*/
redirectsLabel: 'Redirects',
/**
* @description Text for a label describing a network request event as taking too long to start delivery by the server.
*/
serverResponseTimeLabel: 'Server response time',
/**
* @description Text for a label describing a network request event as taking longer to download because it wasn't compressed.
*/
uncompressedDownload: 'Uncompressed download',
};
// const str_ = i18n.i18n.registerUIStrings('models/trace/insights/DocumentLatency.ts', UIStrings);
export const i18nString = (i18nId, values) => ({i18nId, values}); // i18n.i18n.getLocalizedString.bind(undefined, str_);
// Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms.
// We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms.
const TOO_SLOW_THRESHOLD_MS = 600;
const TARGET_MS = 100;
// Threshold for compression savings.
const IGNORE_THRESHOLD_IN_BYTES = 1400;
export function isDocumentLatency(x) {
return x.insightKey === 'DocumentLatency';
}
function getServerResponseTime(request, context) {
// Prefer the value as given by the Lantern provider.
// For PSI, Lighthouse uses this to set a better value for the server response
// time. For technical reasons, in Lightrider we do not have `sendEnd` timing
// values. See Lighthouse's `asLanternNetworkRequest` function for more.
const lanternRequest = context.navigation && context.lantern?.requests.find(r => r.rawRequest === request);
if (lanternRequest?.serverResponseTime !== undefined) {
return lanternRequest.serverResponseTime;
}
const timing = request.args.data.timing;
if (!timing) {
return null;
}
const ms = Helpers.Timing.microToMilli(request.args.data.syntheticData.waiting);
return Math.round(ms);
}
function getCompressionSavings(request) {
const isCompressed = isRequestCompressed(request);
if (isCompressed) {
return 0;
}
// We don't know how many bytes this asset used on the network, but we can guess it was
// roughly the size of the content gzipped.
// See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples
// See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers
// See https://letstalkaboutwebperf.com/en/gzip-brotli-server-config/ for MIME types to compress
const originalSize = request.args.data.decodedBodyLength;
let estimatedSavings = 0;
switch (request.args.data.mimeType) {
case 'text/css':
// Stylesheets tend to compress extremely well.
estimatedSavings = Math.round(originalSize * 0.8);
break;
case 'text/html':
case 'text/javascript':
// Scripts and HTML compress fairly well too.
estimatedSavings = Math.round(originalSize * 0.67);
break;
case 'text/plain':
case 'text/xml':
case 'text/x-component':
case 'application/javascript':
case 'application/json':
case 'application/manifest+json':
case 'application/vnd.api+json':
case 'application/xml':
case 'application/xhtml+xml':
case 'application/rss+xml':
case 'application/atom+xml':
case 'application/vnd.ms-fontobject':
case 'application/x-font-ttf':
case 'application/x-font-opentype':
case 'application/x-font-truetype':
case 'image/svg+xml':
case 'image/x-icon':
case 'image/vnd.microsoft.icon':
case 'font/ttf':
case 'font/eot':
case 'font/otf':
case 'font/opentype':
// Use the average savings in HTTPArchive.
estimatedSavings = Math.round(originalSize * 0.5);
break;
default: // Any other MIME types are likely already compressed.
}
// Check if the estimated savings are greater than the byte ignore threshold.
// Note that the estimated gzip savings are always more than 10%, so there is
// no percent threshold.
return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;
}
function finalize(partialModel) {
let hasFailure = false;
if (partialModel.data) {
hasFailure = !partialModel.data.checklist.usesCompression.value ||
!partialModel.data.checklist.serverResponseIsFast.value || !partialModel.data.checklist.noRedirects.value;
}
return {
insightKey: InsightKeys.DOCUMENT_LATENCY,
strings: UIStrings,
title: i18nString(UIStrings.title),
description: i18nString(UIStrings.description),
category: InsightCategory.ALL,
state: hasFailure ? 'fail' : 'pass',
...partialModel,
};
}
export function generateInsight(parsedTrace, context) {
if (!context.navigation) {
return finalize({});
}
const documentRequest = parsedTrace.NetworkRequests.byId.get(context.navigationId);
if (!documentRequest) {
return finalize({ warnings: [InsightWarning.NO_DOCUMENT_REQUEST] });
}
const serverResponseTime = getServerResponseTime(documentRequest, context);
if (serverResponseTime === null) {
throw new Error('missing document request timing');
}
const serverResponseTooSlow = serverResponseTime > TOO_SLOW_THRESHOLD_MS;
let overallSavingsMs = 0;
if (serverResponseTime > TOO_SLOW_THRESHOLD_MS) {
overallSavingsMs = Math.max(serverResponseTime - TARGET_MS, 0);
}
const redirectDuration = Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000);
overallSavingsMs += redirectDuration;
const metricSavings = {
FCP: overallSavingsMs,
LCP: overallSavingsMs,
};
const uncompressedResponseBytes = getCompressionSavings(documentRequest);
const noRedirects = redirectDuration === 0;
const serverResponseIsFast = !serverResponseTooSlow;
const usesCompression = uncompressedResponseBytes === 0;
return finalize({
relatedEvents: [documentRequest],
data: {
serverResponseTime,
redirectDuration: Types.Timing.Milli(redirectDuration),
uncompressedResponseBytes,
documentRequest,
checklist: {
noRedirects: {
label: noRedirects ? i18nString(UIStrings.passingRedirects) : i18nString(UIStrings.failedRedirects, {
PH1: documentRequest.args.data.redirects.length,
PH2: (bytes => ({__i18nMillis: bytes}))(redirectDuration),
}),
value: noRedirects
},
serverResponseIsFast: {
label: serverResponseIsFast ?
i18nString(UIStrings.passingServerResponseTime, { PH1: (bytes => ({__i18nMillis: bytes}))(serverResponseTime) }) :
i18nString(UIStrings.failedServerResponseTime, { PH1: (bytes => ({__i18nMillis: bytes}))(serverResponseTime) }),
value: serverResponseIsFast
},
usesCompression: {
label: usesCompression ? i18nString(UIStrings.passingTextCompression) :
i18nString(UIStrings.failedTextCompression),
value: usesCompression
},
},
},
metricSavings,
wastedBytes: uncompressedResponseBytes,
});
}
export function createOverlays(model) {
if (!model.data?.documentRequest) {
return [];
}
const overlays = [];
const event = model.data.documentRequest;
const redirectDurationMicro = Helpers.Timing.milliToMicro(model.data.redirectDuration);
const sections = [];
if (model.data.redirectDuration) {
const bounds = Helpers.Timing.traceWindowFromMicroSeconds(event.ts, (event.ts + redirectDurationMicro));
sections.push({ bounds, label: i18nString(UIStrings.redirectsLabel), showDuration: true });
overlays.push({ type: 'CANDY_STRIPED_TIME_RANGE', bounds, entry: event });
}
if (!model.data.checklist.serverResponseIsFast.value) {
const serverResponseTimeMicro = Helpers.Timing.milliToMicro(model.data.serverResponseTime);
// NOTE: NetworkRequestHandlers never makes a synthetic network request event if `timing` is missing.
const sendEnd = event.args.data.timing?.sendEnd ?? Types.Timing.Milli(0);
const sendEndMicro = Helpers.Timing.milliToMicro(sendEnd);
const bounds = Helpers.Timing.traceWindowFromMicroSeconds(sendEndMicro, (sendEndMicro + serverResponseTimeMicro));
sections.push({ bounds, label: i18nString(UIStrings.serverResponseTimeLabel), showDuration: true });
}
if (model.data.uncompressedResponseBytes) {
const bounds = Helpers.Timing.traceWindowFromMicroSeconds(event.args.data.syntheticData.downloadStart, (event.args.data.syntheticData.downloadStart + event.args.data.syntheticData.download));
sections.push({ bounds, label: i18nString(UIStrings.uncompressedDownload), showDuration: true });
overlays.push({ type: 'CANDY_STRIPED_TIME_RANGE', bounds, entry: event });
}
if (sections.length) {
overlays.push({
type: 'TIMESPAN_BREAKDOWN',
sections,
entry: model.data.documentRequest,
// Always render below because the document request is guaranteed to be
// the first request in the network track.
renderLocation: 'BELOW_EVENT',
});
}
overlays.push({
type: 'ENTRY_SELECTED',
entry: model.data.documentRequest,
});
return overlays;
}
//# sourceMappingURL=DocumentLatency.js.map