11
11
'use strict' ;
12
12
13
13
const log = require ( 'lighthouse-logger' ) ;
14
- const Gatherer = require ( '../gatherer.js' ) ;
14
+ const FRGatherer = require ( '../../../fraggle-rock/gather/base- gatherer.js' ) ;
15
15
const URL = require ( '../../../lib/url-shim.js' ) ;
16
16
const NetworkRequest = require ( '../../../lib/network-request.js' ) ;
17
17
const Sentry = require ( '../../../lib/sentry.js' ) ;
18
- const Driver = require ( '../../driver.js' ) ; // eslint-disable-line no-unused-vars
18
+ const NetworkRecords = require ( '../../../computed/network-records.js' ) ;
19
+ const DevtoolsLog = require ( '../devtools-log.js' ) ;
19
20
20
21
// Image encoding can be slow and we don't want to spend forever on it.
21
22
// Cap our encoding to 5 seconds, anything after that will be estimated.
@@ -32,7 +33,13 @@ const IMAGE_REGEX = /^image\/((x|ms|x-ms)-)?(png|bmp|jpeg)$/;
32
33
33
34
/** @typedef {{requestId: string, url: string, mimeType: string, resourceSize: number} } SimplifiedNetworkRecord */
34
35
35
- class OptimizedImages extends Gatherer {
36
+ class OptimizedImages extends FRGatherer {
37
+ /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'> } */
38
+ meta = {
39
+ supportedModes : [ 'timespan' , 'navigation' ] ,
40
+ dependencies : { DevtoolsLog : DevtoolsLog . symbol } ,
41
+ }
42
+
36
43
constructor ( ) {
37
44
super ( ) ;
38
45
this . _encodingStartAt = 0 ;
@@ -70,25 +77,25 @@ class OptimizedImages extends Gatherer {
70
77
}
71
78
72
79
/**
73
- * @param {Driver } driver
80
+ * @param {LH.Gatherer.FRProtocolSession } session
74
81
* @param {string } requestId
75
82
* @param {'jpeg'|'webp' } encoding Either webp or jpeg.
76
83
* @return {Promise<LH.Crdp.Audits.GetEncodedResponseResponse> }
77
84
*/
78
- _getEncodedResponse ( driver , requestId , encoding ) {
85
+ _getEncodedResponse ( session , requestId , encoding ) {
79
86
requestId = NetworkRequest . getRequestIdForBackend ( requestId ) ;
80
87
81
88
const quality = encoding === 'jpeg' ? JPEG_QUALITY : WEBP_QUALITY ;
82
89
const params = { requestId, encoding, quality, sizeOnly : true } ;
83
- return driver . sendCommand ( 'Audits.getEncodedResponse' , params ) ;
90
+ return session . sendCommand ( 'Audits.getEncodedResponse' , params ) ;
84
91
}
85
92
86
93
/**
87
- * @param {Driver } driver
94
+ * @param {LH.Gatherer.FRProtocolSession } session
88
95
* @param {SimplifiedNetworkRecord } networkRecord
89
96
* @return {Promise<{originalSize: number, jpegSize?: number, webpSize?: number}> }
90
97
*/
91
- async calculateImageStats ( driver , networkRecord ) {
98
+ async calculateImageStats ( session , networkRecord ) {
92
99
const originalSize = networkRecord . resourceSize ;
93
100
// Once we've hit our execution time limit or when the image is too big, don't try to re-encode it.
94
101
// Images in this execution path will fallback to byte-per-pixel heuristics on the audit side.
@@ -97,8 +104,8 @@ class OptimizedImages extends Gatherer {
97
104
return { originalSize, jpegSize : undefined , webpSize : undefined } ;
98
105
}
99
106
100
- const jpegData = await this . _getEncodedResponse ( driver , networkRecord . requestId , 'jpeg' ) ;
101
- const webpData = await this . _getEncodedResponse ( driver , networkRecord . requestId , 'webp' ) ;
107
+ const jpegData = await this . _getEncodedResponse ( session , networkRecord . requestId , 'jpeg' ) ;
108
+ const webpData = await this . _getEncodedResponse ( session , networkRecord . requestId , 'webp' ) ;
102
109
103
110
return {
104
111
originalSize,
@@ -108,19 +115,19 @@ class OptimizedImages extends Gatherer {
108
115
}
109
116
110
117
/**
111
- * @param {Driver } driver
118
+ * @param {LH.Gatherer.FRProtocolSession } session
112
119
* @param {Array<SimplifiedNetworkRecord> } imageRecords
113
120
* @return {Promise<LH.Artifacts['OptimizedImages']> }
114
121
*/
115
- async computeOptimizedImages ( driver , imageRecords ) {
122
+ async computeOptimizedImages ( session , imageRecords ) {
116
123
this . _encodingStartAt = Date . now ( ) ;
117
124
118
125
/** @type {LH.Artifacts['OptimizedImages'] } */
119
126
const results = [ ] ;
120
127
121
128
for ( const record of imageRecords ) {
122
129
try {
123
- const stats = await this . calculateImageStats ( driver , record ) ;
130
+ const stats = await this . calculateImageStats ( session , record ) ;
124
131
/** @type {LH.Artifacts.OptimizedImage } */
125
132
const image = { failed : false , ...stats , ...record } ;
126
133
results . push ( image ) ;
@@ -145,26 +152,40 @@ class OptimizedImages extends Gatherer {
145
152
}
146
153
147
154
/**
148
- * @param {LH.Gatherer.PassContext } passContext
149
- * @param {LH.Gatherer.LoadData } loadData
155
+ * @param {LH.Gatherer.FRTransitionalContext } context
156
+ * @param {LH.Artifacts.NetworkRequest[] } networkRecords
150
157
* @return {Promise<LH.Artifacts['OptimizedImages']> }
151
158
*/
152
- afterPass ( passContext , loadData ) {
153
- const networkRecords = loadData . networkRecords ;
159
+ async _getArtifact ( context , networkRecords ) {
154
160
const imageRecords = OptimizedImages
155
161
. filterImageRequests ( networkRecords )
156
162
. sort ( ( a , b ) => b . resourceSize - a . resourceSize ) ;
157
163
158
- return Promise . resolve ( )
159
- . then ( _ => this . computeOptimizedImages ( passContext . driver , imageRecords ) )
160
- . then ( results => {
161
- const successfulResults = results . filter ( result => ! result . failed ) ;
162
- if ( results . length && ! successfulResults . length ) {
163
- throw new Error ( 'All image optimizations failed' ) ;
164
- }
164
+ const results = await this . computeOptimizedImages ( context . driver . defaultSession , imageRecords ) ;
165
+ const successfulResults = results . filter ( result => ! result . failed ) ;
166
+ if ( results . length && ! successfulResults . length ) {
167
+ throw new Error ( 'All image optimizations failed' ) ;
168
+ }
169
+ return results ;
170
+ }
165
171
166
- return results ;
167
- } ) ;
172
+ /**
173
+ * @param {LH.Gatherer.FRTransitionalContext<'DevtoolsLog'> } context
174
+ * @return {Promise<LH.Artifacts['OptimizedImages']> }
175
+ */
176
+ async getArtifact ( context ) {
177
+ const devtoolsLog = context . dependencies . DevtoolsLog ;
178
+ const networkRecords = await NetworkRecords . request ( devtoolsLog , context ) ;
179
+ return this . _getArtifact ( context , networkRecords ) ;
180
+ }
181
+
182
+ /**
183
+ * @param {LH.Gatherer.PassContext } passContext
184
+ * @param {LH.Gatherer.LoadData } loadData
185
+ * @return {Promise<LH.Artifacts['OptimizedImages']> }
186
+ */
187
+ async afterPass ( passContext , loadData ) {
188
+ return this . _getArtifact ( { ...passContext , dependencies : { } } , loadData . networkRecords ) ;
168
189
}
169
190
}
170
191
0 commit comments