UNPKG

lighthouse

Version:

Automated auditing, performance metrics, and best practices for the web.

369 lines (334 loc) • 11.1 kB
/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import {IcuMessage} from './i18n.js'; import Treemap from './treemap.js'; /** Common properties for all details types. */ interface BaseDetails { /** Additional information, usually used for including debug or meta information in the LHR */ debugData?: Details.DebugData; } type Details = Details.CriticalRequestChain | Details.NetworkTree | Details.DebugData | Details.TreemapData | Details.Filmstrip | Details.List | Details.Opportunity | Details.Screenshot | Details.Checklist | Details.Table; // Details namespace. declare module Details { type NetworkNode = { [id: string]: { url: string; /** In ms */ navStartToEndTime: number; transferSize: number; isLongest?: boolean; children?: NetworkNode; } }; /** * This detail type is introduced to address the differences in how the RPP network tree is displayed vs the old Lighthouse CRC audit: * - The CRC audit will show individual request durations but the new NDT insight will show the entire chain duration * - The CRC audit will only show any timing/size for leaf node requests, but the NDT insight will show this info for all requests * - The CRC audit contains extra request timing info like `responseReceivedTime` but we don't need this for the NDT insight. * The NDT insight has enough information to fill in this extra data, but we shouldn't add calculations just to fill in the CRC detail type. */ interface NetworkTree extends BaseDetails { type: 'network-tree'; longestChain: { /** In ms */ duration: number; }; chains: NetworkNode; } interface CriticalRequestChain extends BaseDetails { type: 'criticalrequestchain'; longestChain: { /** In ms */ duration: number; length: number; transferSize: number; }; chains: SimpleCriticalRequestNode; } type SimpleCriticalRequestNode = { [id: string]: { request: { url: string; /** In seconds */ startTime: number; /** In seconds */ endTime: number; /** In seconds */ responseReceivedTime: number; transferSize: number; }; children?: SimpleCriticalRequestNode; } } interface Filmstrip extends BaseDetails { type: 'filmstrip'; scale: number; items: { /** The relative time from navigationStart to this frame, in milliseconds. */ timing: number; /** The raw timestamp of this frame, in microseconds. */ timestamp: number; /** The data URL encoding of this frame. */ data: string; }[]; } // NOTE: any `Details` type *should* be usable in `items`, but check // styles/report-ui-features are good before adding. type ListableDetail = Table | Checklist | NetworkTree | NodeValue | TextValue | DebugData; interface ListSectionItem { type: 'list-section'; title?: IcuMessage | string; description?: IcuMessage | string; value: ListableDetail; } interface List extends BaseDetails { type: 'list'; items: Array<ListSectionItem | ListableDetail>; } interface Opportunity extends BaseDetails { type: 'opportunity'; headings: TableColumnHeading[]; items: OpportunityItem[]; /** * Columns to sort the items by, during grouping. * If omitted, entity groups will be sorted by the audit ordering vs. the new totals. */ sortedBy?: Array<string>; /** Will be true if the table is already grouped by entities. */ isEntityGrouped?: boolean; /** Column keys to skip summing. If omitted, all column types supported are summed. */ skipSumming?: Array<string>; /** * @deprecated * Historically this represents the time saved on the entire page load. It's mostly used as an * alias for `metricSavings.LCP` now. We recommend using `metricSavings` directly for more * metric-specific savings estimates. */ overallSavingsMs?: number; /** Total byte savings covered by this audit. */ overallSavingsBytes?: number; } interface Screenshot extends BaseDetails { type: 'screenshot'; timing: number; timestamp: number; data: string; } interface Rect { width: number; height: number; top: number; right: number; bottom: number; left: number; } interface Checklist extends BaseDetails { type: 'checklist', items: Record<string, {value: boolean, label: IcuMessage | string}>, } interface Table extends BaseDetails { type: 'table'; headings: TableColumnHeading[]; items: TableItem[]; summary?: { wastedMs?: number; wastedBytes?: number; }; /** * Columns to sort the items by, during grouping. * If omitted, entity groups will be sorted by the audit ordering vs. the new totals. */ sortedBy?: Array<string>; /** Will be true if the table is already grouped by entities. */ isEntityGrouped?: boolean; /** Column keys to skip summing. If omitted, all column types supported are summed. */ skipSumming?: Array<string>; } /** A table item for rows that are nested within a top-level TableItem (row). */ interface TableSubItems { type: 'subitems'; items: TableItem[]; } /** * A details type that is not rendered in the final report; usually used * for including debug information in the LHR. Can contain anything. */ interface DebugData { type: 'debugdata'; [p: string]: any; } interface TreemapData extends BaseDetails { type: 'treemap-data'; nodes: Treemap.Node[]; } /** String enum of possible types of values found within table items. */ type ItemValueType = 'bytes' | 'code' | 'link' | 'ms' | 'multi' | 'node' | 'source-location' | 'numeric' | 'text' | 'thumbnail' | 'timespanMs' | 'url'; /** Possible types of values found within table items. */ type ItemValue = string | number | boolean | DebugData | NodeValue | SourceLocationValue | LinkValue | UrlValue | CodeValue | NumericValue | TextValue | IcuMessage | TableSubItems; interface TableColumnHeading { /** * The name of the property within items being described. * If null, subItemsHeading must be defined, and the first table row in this column for * every item will be empty. * See legacy-javascript for an example. */ key: string|null; /** Readable text label of the field. */ label: IcuMessage | string; /** * The data format of the column of values being described. Usually * those values will be primitives rendered as this type, but the values * could also be objects with their own type to override this field. */ valueType: ItemValueType; /** * Optional - defines an inner table of values that correspond to this column. * Key is required - if other properties are not provided, the value for the heading is used. */ subItemsHeading?: {key: string, valueType?: ItemValueType, displayUnit?: string, granularity?: number}; displayUnit?: string; granularity?: number; } interface TableItem { debugData?: DebugData; subItems?: TableSubItems; [p: string]: undefined | ItemValue; } /** A more specific table element used for `opportunity` tables. */ interface OpportunityItem extends TableItem { url: string; wastedBytes?: number; totalBytes?: number; wastedMs?: number; debugData?: DebugData; [p: string]: undefined | ItemValue; } /** * A value used within a details object, intended to be displayed as code, * regardless of the controlling heading's valueType. */ interface CodeValue { type: 'code'; value: IcuMessage | string; } /** * A value used within a details object, intended to be displayed as a * link with text, regardless of the controlling heading's valueType. * If URL is the empty string, fallsback to a basic `TextValue`. */ interface LinkValue { type: 'link', text: string; url: string; } /** * A value used within a details object, intended to be displayed an HTML * node, regardless of the controlling heading's valueType. */ interface NodeValue { type: 'node'; /** Unique identifier. */ lhId?: string; path?: string; selector?: string; boundingRect?: Rect; /** An HTML snippet used to identify the node. */ snippet?: string; /** A human-friendly text descriptor that's used to identify the node more quickly. */ nodeLabel?: string; /** A human-friendly explainer on how to approach the possible fix. */ explanation?: string; } /** * A value used within a details object, intended to be displayed as a URL * encoded with line and column info (url:line:column). */ interface SourceLocationValue { type: 'source-location'; /** A "url" representing the source file. May not be a valid URL, see `urlProvider`. */ url: string; /** * - `network` when the url is the actual, observed resource url. This is always a valid URL. * - `comment` when the url comes from a sourceURL comment. This could be anything, really. */ urlProvider: 'network' | 'comment'; /** Zero-indexed. */ line: number; /** Zero-indexed. */ column: number; /** The original file location from the source map. */ original?: { /** The relevant file from the map's `sources` array. */ file: string; line: number; column: number; }; functionName?: string; } /** * A value used within a details object, intended to be displayed as a * linkified URL, regardless of the controlling heading's valueType. */ interface UrlValue { type: 'url'; value: string; } /** * Snippet of text with line numbers and annotations. */ interface SnippetValue { type: 'snippet', title: string, /** Node where the content of this snippet came from. */ node?: NodeValue, /** * The lines that should be rendered. For long snippets we only include important lines * in the audit result. */ lines: { content: string /** Line number, starting from 1. */ lineNumber: number; truncated?: boolean }[], /** The total number of lines in the snippet, equal to lines.length for short snippets. */ lineCount: number, /** Messages that provide information about a specific lines. */ lineMessages: { /** Line number, starting from 1. */ lineNumber: number, message: string }[]; /** Messages that provide information about the snippet in general. */ generalMessages: { message: string }[]; } /** * A value used within a details object, intended to be displayed as a ms timing * or a numeric value based on the metric name. */ interface NumericValue { type: 'numeric', value: number, granularity?: number, } interface TextValue { type: 'text', value: IcuMessage | string, } } export default Details;