-
Notifications
You must be signed in to change notification settings - Fork 9.5k
/
Copy pathnetwork-requests.js
136 lines (123 loc) · 4.97 KB
/
network-requests.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {Audit} from './audit.js';
import UrlUtils from '../lib/url-utils.js';
import {NetworkRecords} from '../computed/network-records.js';
import {MainResource} from '../computed/main-resource.js';
import {EntityClassification} from '../computed/entity-classification.js';
class NetworkRequests extends Audit {
/**
* @return {LH.Audit.Meta}
*/
static get meta() {
return {
id: 'network-requests',
scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
title: 'Network Requests',
description: 'Lists the network requests that were made during page load.',
requiredArtifacts: ['devtoolsLogs', 'URL', 'GatherContext'],
};
}
/**
* @param {LH.Artifacts} artifacts
* @param {LH.Audit.Context} context
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const records = await NetworkRecords.request(devtoolsLog, context);
const classifiedEntities = await EntityClassification.request(
{URL: artifacts.URL, devtoolsLog}, context);
const earliestRendererStartTime = records.reduce(
(min, record) => Math.min(min, record.rendererStartTime),
Infinity
);
// Optional mainFrameId check because the main resource is only available for
// navigations. TODO: https://github.com/GoogleChrome/lighthouse/issues/14157
// for the general solution to this.
/** @type {string|undefined} */
let mainFrameId;
if (artifacts.GatherContext.gatherMode === 'navigation') {
const mainResource = await MainResource.request({devtoolsLog, URL: artifacts.URL}, context);
mainFrameId = mainResource.frameId;
}
/** @param {number} time */
const normalizeTime = time => time < earliestRendererStartTime || !Number.isFinite(time) ?
undefined : (time - earliestRendererStartTime);
const results = records.map(record => {
const endTimeDeltaMs = record.lrStatistics?.endTimeDeltaMs;
const TCPMs = record.lrStatistics?.TCPMs;
const requestMs = record.lrStatistics?.requestMs;
const responseMs = record.lrStatistics?.responseMs;
// Default these to undefined so omitted from JSON in the negative case.
const isLinkPreload = record.isLinkPreload || undefined;
const experimentalFromMainFrame = mainFrameId ?
((record.frameId === mainFrameId) || undefined) :
undefined;
const entity = classifiedEntities.entityByUrl.get(record.url);
return {
url: UrlUtils.elideDataURI(record.url),
sessionTargetType: record.sessionTargetType,
protocol: record.protocol,
rendererStartTime: normalizeTime(record.rendererStartTime),
networkRequestTime: normalizeTime(record.networkRequestTime),
networkEndTime: normalizeTime(record.networkEndTime),
finished: record.finished,
transferSize: record.transferSize,
resourceSize: record.resourceSize,
statusCode: record.statusCode,
mimeType: record.mimeType,
resourceType: record.resourceType,
priority: record.priority,
isLinkPreload,
experimentalFromMainFrame,
entity: entity?.name,
lrEndTimeDeltaMs: endTimeDeltaMs, // Only exists on Lightrider runs
lrTCPMs: TCPMs, // Only exists on Lightrider runs
lrRequestMs: requestMs, // Only exists on Lightrider runs
lrResponseMs: responseMs, // Only exists on Lightrider runs
};
});
// NOTE(i18n): this audit is only for debug info in the LHR and does not appear in the report.
/** @type {LH.Audit.Details.Table['headings']} */
const headings = [
{key: 'url', valueType: 'url', label: 'URL'},
{key: 'protocol', valueType: 'text', label: 'Protocol'},
{key: 'networkRequestTime', valueType: 'ms', granularity: 1, label: 'Network Request Time'},
{key: 'networkEndTime', valueType: 'ms', granularity: 1, label: 'Network End Time'},
{
key: 'transferSize',
valueType: 'bytes',
displayUnit: 'kb',
granularity: 1,
label: 'Transfer Size',
},
{
key: 'resourceSize',
valueType: 'bytes',
displayUnit: 'kb',
granularity: 1,
label: 'Resource Size',
},
{key: 'statusCode', valueType: 'text', label: 'Status Code'},
{key: 'mimeType', valueType: 'text', label: 'MIME Type'},
{key: 'resourceType', valueType: 'text', label: 'Resource Type'},
];
const tableDetails = Audit.makeTableDetails(headings, results);
// Include starting timestamp to allow syncing requests with navStart/metric timestamps.
const networkStartTimeTs = Number.isFinite(earliestRendererStartTime) ?
earliestRendererStartTime * 1000 : undefined;
tableDetails.debugData = {
type: 'debugdata',
networkStartTimeTs,
};
return {
score: 1,
details: tableDetails,
};
}
}
export default NetworkRequests;