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>
96 lines
2.7 KiB
Text
96 lines
2.7 KiB
Text
/**
|
|
* @license
|
|
* Copyright 2018 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* Generates a chromium trace file from user timing measures
|
|
* `threadId` can be provided to separate a series of trace events into another thread, useful
|
|
* if timings do not share the same timeOrigin, but should both be "left-aligned".
|
|
* Adapted from https://github.com/tdresser/performance-observer-tracing
|
|
* @param {LH.Artifacts.MeasureEntry[]} entries user timing entries
|
|
* @param {number=} threadId
|
|
*/
|
|
function generateTraceEvents(entries, threadId = 0) {
|
|
if (!Array.isArray(entries)) return [];
|
|
|
|
/** @type {LH.TraceEvent[]} */
|
|
const currentTrace = [];
|
|
entries.sort((a, b) => a.startTime - b.startTime);
|
|
entries.forEach((entry, i) => {
|
|
/** @type {LH.TraceEvent} */
|
|
const startEvt = {
|
|
// 1) Remove 'lh:' for readability
|
|
// 2) Colons in user_timing names get special handling in traceviewer we don't want. https://goo.gl/m23Vz7
|
|
// Replace with a 'Modifier letter colon' ;)
|
|
name: entry.name.replace('lh:', '').replace(/:/g, '\ua789'),
|
|
cat: 'blink.user_timing',
|
|
ts: entry.startTime * 1000,
|
|
args: {},
|
|
dur: 0,
|
|
pid: 0,
|
|
tid: threadId,
|
|
ph: 'b',
|
|
id: '0x' + (i++).toString(16),
|
|
};
|
|
|
|
const endEvt = JSON.parse(JSON.stringify(startEvt));
|
|
endEvt.ph = 'e';
|
|
endEvt.ts = startEvt.ts + (entry.duration * 1000);
|
|
|
|
currentTrace.push(startEvt);
|
|
currentTrace.push(endEvt);
|
|
});
|
|
|
|
// Add labels
|
|
/** @type {LH.TraceEvent} */
|
|
const metaEvtBase = {
|
|
pid: 0,
|
|
tid: threadId,
|
|
ts: 0,
|
|
dur: 0,
|
|
ph: 'M',
|
|
cat: '__metadata',
|
|
name: 'process_labels',
|
|
args: {labels: 'Default'},
|
|
};
|
|
currentTrace.push(Object.assign({}, metaEvtBase, {args: {labels: 'Lighthouse Timing'}}));
|
|
|
|
// Only inject TracingStartedInBrowser once
|
|
if (threadId === 0) {
|
|
currentTrace.push(Object.assign({}, metaEvtBase, {
|
|
'cat': 'disabled-by-default-devtools.timeline',
|
|
'name': 'TracingStartedInBrowser',
|
|
'ph': 'I',
|
|
'args': {'data': {
|
|
'frameTreeNodeId': 1,
|
|
'persistentIds': true,
|
|
'frames': [],
|
|
}},
|
|
}));
|
|
}
|
|
return currentTrace;
|
|
}
|
|
|
|
/**
|
|
* Writes a trace file to disk
|
|
* @param {LH.Result} lhr
|
|
* @return {string}
|
|
*/
|
|
function createTraceString(lhr) {
|
|
const gatherEntries = lhr.timing.entries.filter(entry => entry.gather);
|
|
const entries = lhr.timing.entries.filter(entry => !gatherEntries.includes(entry));
|
|
|
|
const auditEvents = generateTraceEvents(entries);
|
|
const gatherEvents = generateTraceEvents(gatherEntries, 10);
|
|
const events = [...auditEvents, ...gatherEvents];
|
|
|
|
const jsonStr = `{"traceEvents":[
|
|
${events.map(evt => JSON.stringify(evt)).join(',\n')}
|
|
]}`;
|
|
|
|
return jsonStr;
|
|
}
|
|
|
|
export {generateTraceEvents, createTraceString};
|