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>
1 line
No EOL
12 KiB
Text
1 line
No EOL
12 KiB
Text
{"version":3,"file":"FirstContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAC,MAAM,EAA0B,MAAM,aAAa,CAAC;AAoB5D,MAAM,oBAAqB,SAAQ,MAAM;IACvC,MAAM,KAAc,YAAY;QAC9B,OAAO;YACL,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,GAAG;SACjB,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,yBAAyB,CAC5B,KAAiB,EACjB,EAAC,eAAe,EAAE,yBAAyB,EAAE,yCAAyC,EACvD;QAEjC,iGAAiG;QACjG,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAyB,CAAC;QAE5D,MAAM,QAAQ,GAAoB,EAAE,CAAC;QACrC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YACpB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC3C,+EAA+E;gBAC/E,mGAAmG;gBACnG,IAAI,IAAI,CAAC,SAAS,IAAI,eAAe,EAAE,CAAC;oBACtC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,CAAC;gBAED,0EAA0E;gBAC1E,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAChD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;oBAC7B,qCAAqC;oBACrC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;oBACrD,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBACrF,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAEnD,wFAAwF;QACxF,MAAM,gCAAgC,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE;YAC1E,6FAA6F;YAC7F,wFAAwF;YACxF,+DAA+D;YAC/D,OAAO,IAAI,CAAC,OAAO,IAAI,eAAe,IAAI,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,yGAAyG;QACzG,MAAM,qCAAqC,GAAG,IAAI,GAAG,EAAU,CAAC;QAChE,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAU,CAAC;QACnD,KAAK,MAAM,GAAG,IAAI,gCAAgC,EAAE,CAAC;YACnD,yEAAyE;YACzE,MAAM,aAAa,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAElD,2EAA2E;YAC3E,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,SAAS;YACX,CAAC;YAED,kIAAkI;YAClI,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACrC,wBAAwB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,6FAA6F;YAC7F,iDAAiD;YACjD,qCAAqC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjD,CAAC;QAED,kGAAkG;QAClG,wCAAwC;QACxC,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACnE,IAAI,WAAW,EAAE,CAAC;YAChB,wBAAwB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC;QACzF,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC;QAC7F,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,4EAA4E;QAC5E,IAAI,yCAAyC,EAAE,CAAC;YAC9C,QAAQ,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACpH,CAAC;QAED,OAAO;YACL,qCAAqC;YACrC,wBAAwB;SACzB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,uBAAuB,CAC1B,eAA2B,EAC3B,EAAC,eAAe,EAAE,yBAAyB,EAAE,yCAAyC,EACvD;QAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE;YAC7D,eAAe;YACf,yBAAyB;YACzB,yCAAyC;SAC1C,CAAC,CAAC;QACH,MAAM,EAAC,qCAAqC,EAAE,wBAAwB,EAAC,GAAG,MAAM,CAAC;QAEjF,OAAO,eAAe,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE;YACnD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,uHAAuH;gBACvH,gHAAgH;gBAChH,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,GAAG,eAAe,IAAI,IAAI,CAAC,SAAS,GAAG,eAAe,CAAC;gBAC3F,IAAI,eAAe,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC9C,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC7B,sEAAsE;gBACtE,IAAI,qCAAqC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnD,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,0EAA0E;gBAC1E,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;YACD,qDAAqD;YACrD,OAAO,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAU,kBAAkB,CAC9B,eAA8B,EAAE,mBAAyD;QAC3F,OAAO,IAAI,CAAC,uBAAuB,CAAC,eAAe,EAAE;YACnD,eAAe,EAAE,mBAAmB,CAAC,UAAU,CAAC,oBAAoB;YACpE,4FAA4F;YAC5F,6FAA6F;YAC7F,+FAA+F;YAC/F,yBAAyB,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,IAAI,IAAI,CAAC,aAAa,KAAK,QAAQ;SACvG,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAU,mBAAmB,CAC/B,eAA8B,EAAE,mBAAyD;QAC3F,OAAO,IAAI,CAAC,uBAAuB,CAAC,eAAe,EAAE;YACnD,eAAe,EAAE,mBAAmB,CAAC,UAAU,CAAC,oBAAoB;YACpE,yBAAyB,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE;SACpE,CAAC,CAAC;IACL,CAAC;CACF;AAED,OAAO,EAAC,oBAAoB,EAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Graph from '../graph/graph.js';\nimport type * as Types from '../types/types.js';\n\nimport {Metric, type MetricCoefficients} from './Metric.js';\n\ninterface FirstPaintBasedGraphOpts<T> {\n /**\n * The timestamp used to filter out tasks that occurred after our paint of interest.\n * Typically this is First Contentful Paint or First Meaningful Paint.\n */\n cutoffTimestamp: number;\n /**\n * The function that determines which resources should be considered *possibly*\n * render-blocking.\n */\n treatNodeAsRenderBlocking: (node: Graph.NetworkNode<T>) => boolean;\n /**\n * The function that determines which CPU nodes should also be included in our\n * blocking node IDs set, beyond what getRenderBlockingNodeData() already includes.\n */\n additionalCpuNodesToTreatAsRenderBlocking?: (node: Graph.CPUNode) => boolean;\n}\n\nclass FirstContentfulPaint extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n /**\n * Computes the set of URLs that *appeared* to be render-blocking based on our filter,\n * *but definitely were not* render-blocking based on the timing of their EvaluateScript task.\n * It also computes the set of corresponding CPU node ids that were needed for the paint at the\n * given timestamp.\n */\n static getRenderBlockingNodeData<T = unknown>(\n graph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): {definitelyNotRenderBlockingScriptUrls: Set<string>, renderBlockingCpuNodeIds: Set<string>} {\n /** A map of blocking script URLs to the earliest EvaluateScript task node that executed them. */\n const scriptUrlToNodeMap = new Map<string, Graph.CPUNode>();\n\n const cpuNodes: Graph.CPUNode[] = [];\n graph.traverse(node => {\n if (node.type === Graph.BaseNode.types.CPU) {\n // A task is *possibly* render blocking if it *started* before cutoffTimestamp.\n // We use startTime here because the paint event can be *inside* the task that was render blocking.\n if (node.startTime <= cutoffTimestamp) {\n cpuNodes.push(node);\n }\n\n // Build our script URL map to find the earliest EvaluateScript task node.\n const scriptUrls = node.getEvaluateScriptURLs();\n for (const url of scriptUrls) {\n // Use the earliest CPU node we find.\n const existing = scriptUrlToNodeMap.get(url) || node;\n scriptUrlToNodeMap.set(url, node.startTime < existing.startTime ? node : existing);\n }\n }\n });\n\n cpuNodes.sort((a, b) => a.startTime - b.startTime);\n\n // A script is *possibly* render blocking if it finished loading before cutoffTimestamp.\n const possiblyRenderBlockingScriptUrls = Metric.getScriptUrls(graph, node => {\n // The optimistic LCP treatNodeAsRenderBlocking fn wants to exclude some images in the graph,\n // but here it only receives scripts to evaluate. It's a no-op in this case, but it will\n // matter below in the getFirstPaintBasedGraph clone operation.\n return node.endTime <= cutoffTimestamp && treatNodeAsRenderBlocking(node);\n });\n\n // A script is *definitely not* render blocking if its EvaluateScript task started after cutoffTimestamp.\n const definitelyNotRenderBlockingScriptUrls = new Set<string>();\n const renderBlockingCpuNodeIds = new Set<string>();\n for (const url of possiblyRenderBlockingScriptUrls) {\n // Lookup the CPU node that had the earliest EvaluateScript for this URL.\n const cpuNodeForUrl = scriptUrlToNodeMap.get(url);\n\n // If we can't find it at all, we can't conclude anything, so just skip it.\n if (!cpuNodeForUrl) {\n continue;\n }\n\n // If we found it and it was in our `cpuNodes` set that means it finished before cutoffTimestamp, so it really is render-blocking.\n if (cpuNodes.includes(cpuNodeForUrl)) {\n renderBlockingCpuNodeIds.add(cpuNodeForUrl.id);\n continue;\n }\n\n // We couldn't find the evaluate script in the set of CPU nodes that ran before our paint, so\n // it must not have been necessary for the paint.\n definitelyNotRenderBlockingScriptUrls.add(url);\n }\n\n // The first layout, first paint, and first ParseHTML are almost always necessary for first paint,\n // so we always include those CPU nodes.\n const firstLayout = cpuNodes.find(node => node.didPerformLayout());\n if (firstLayout) {\n renderBlockingCpuNodeIds.add(firstLayout.id);\n }\n const firstPaint = cpuNodes.find(node => node.childEvents.some(e => e.name === 'Paint'));\n if (firstPaint) {\n renderBlockingCpuNodeIds.add(firstPaint.id);\n }\n const firstParse = cpuNodes.find(node => node.childEvents.some(e => e.name === 'ParseHTML'));\n if (firstParse) {\n renderBlockingCpuNodeIds.add(firstParse.id);\n }\n\n // If a CPU filter was passed in, we also want to include those extra nodes.\n if (additionalCpuNodesToTreatAsRenderBlocking) {\n cpuNodes.filter(additionalCpuNodesToTreatAsRenderBlocking).forEach(node => renderBlockingCpuNodeIds.add(node.id));\n }\n\n return {\n definitelyNotRenderBlockingScriptUrls,\n renderBlockingCpuNodeIds,\n };\n }\n\n /**\n * Computes the graph required for the first paint of interest.\n */\n static getFirstPaintBasedGraph<T>(\n dependencyGraph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): Graph.Node<T> {\n const rbData = this.getRenderBlockingNodeData(dependencyGraph, {\n cutoffTimestamp,\n treatNodeAsRenderBlocking,\n additionalCpuNodesToTreatAsRenderBlocking,\n });\n const {definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds} = rbData;\n\n return dependencyGraph.cloneWithRelationships(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n // Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)\n // endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.\n const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;\n if (endedAfterPaint && !node.isMainDocument()) {\n return false;\n }\n\n const url = node.request.url;\n // If the URL definitely wasn't render-blocking then we filter it out.\n if (definitelyNotRenderBlockingScriptUrls.has(url)) {\n return false;\n }\n\n // Lastly, build up the FCP graph of all nodes we consider render blocking\n return treatNodeAsRenderBlocking(node);\n }\n // If it's a CPU node, just check if it was blocking.\n return renderBlockingCpuNodeIds.has(node.id);\n });\n }\n\n static override getOptimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n // In the optimistic graph we exclude resources that appeared to be render blocking but were\n // initiated by a script. While they typically have a very high importance and tend to have a\n // significant impact on the page's content, these resources don't technically block rendering.\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority() && node.initiatorType !== 'script',\n });\n }\n\n static override getPessimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority(),\n });\n }\n}\n\nexport {FirstContentfulPaint};\n"]} |