lighthouse 8.4.0 → 8.5.0-dev.20210921
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +79 -0
- package/flow-report/assets/styles.css +85 -61
- package/flow-report/src/app.tsx +6 -2
- package/flow-report/src/common.tsx +0 -41
- package/flow-report/src/icons.tsx +11 -0
- package/flow-report/src/summary/summary.tsx +32 -25
- package/flow-report/src/topbar.tsx +60 -0
- package/flow-report/src/util.ts +0 -1
- package/flow-report/src/wrappers/{gauge.tsx → category-score.tsx} +11 -5
- package/flow-report/test/summary/summary-test.tsx +3 -3
- package/flow-report/tsconfig.json +6 -22
- package/{lighthouse-core/gather/gatherers/gather-context.js → lighthouse-cli/.eslintrc.cjs} +20 -18
- package/lighthouse-cli/bin.js +31 -21
- package/lighthouse-cli/cli-flags.js +12 -7
- package/lighthouse-cli/commands/commands.js +2 -7
- package/lighthouse-cli/commands/list-audits.js +2 -2
- package/lighthouse-cli/commands/list-trace-categories.js +2 -2
- package/lighthouse-cli/index.js +3 -1
- package/lighthouse-cli/package.json +4 -0
- package/lighthouse-cli/printer.js +4 -3
- package/lighthouse-cli/run.js +14 -15
- package/lighthouse-cli/sentry-prompt.js +5 -6
- package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/lib.js +5 -4
- package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +93 -14
- package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -1
- package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -1
- package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -1
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +20 -16
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +15 -12
- package/lighthouse-cli/test/smokehouse/report-assert.js +23 -13
- package/lighthouse-cli/test/smokehouse/smokehouse.js +32 -11
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +0 -2
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +6 -1
- package/lighthouse-core/audits/dobetterweb/js-libraries.js +5 -0
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -0
- package/lighthouse-core/audits/lcp-lazy-loaded.js +1 -0
- package/lighthouse-core/audits/oopif-iframe-test-audit.js +30 -0
- package/lighthouse-core/computed/metrics/metric.js +2 -1
- package/lighthouse-core/config/config-helpers.js +47 -3
- package/lighthouse-core/config/config.js +3 -46
- package/lighthouse-core/config/default-config.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +22 -4
- package/lighthouse-core/fraggle-rock/config/default-config.js +0 -9
- package/lighthouse-core/fraggle-rock/config/filters.js +3 -0
- package/lighthouse-core/fraggle-rock/config/validation.js +19 -1
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +8 -3
- package/lighthouse-core/fraggle-rock/gather/driver.js +10 -0
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +40 -19
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
- package/lighthouse-core/fraggle-rock/gather/session.js +44 -1
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -1
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +5 -1
- package/lighthouse-core/gather/devtools-log.js +9 -3
- package/lighthouse-core/gather/driver/network-monitor.js +57 -13
- package/lighthouse-core/gather/driver/prepare.js +43 -17
- package/lighthouse-core/gather/driver/target-manager.js +125 -0
- package/lighthouse-core/gather/driver.js +20 -0
- package/lighthouse-core/gather/fetcher.js +2 -2
- package/lighthouse-core/gather/gather-runner.js +1 -1
- package/lighthouse-core/gather/gatherers/css-usage.js +0 -2
- package/lighthouse-core/gather/gatherers/devtools-log.js +11 -9
- package/lighthouse-core/gather/gatherers/js-usage.js +0 -1
- package/lighthouse-core/gather/gatherers/script-elements.js +4 -5
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +3 -3
- package/lighthouse-core/gather/gatherers/trace.js +4 -5
- package/lighthouse-core/index.js +4 -0
- package/lighthouse-core/lib/emulation.js +0 -1
- package/lighthouse-core/lib/i18n/locales/en-US.json +6 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +6 -0
- package/lighthouse-core/lib/network-recorder.js +8 -0
- package/lighthouse-core/lib/proto-preprocessor.js +5 -10
- package/lighthouse-core/runner.js +1 -3
- package/package.json +12 -9
- package/readme.md +2 -0
- package/report/assets/styles.css +120 -12
- package/report/assets/templates.html +13 -0
- package/report/clients/psi.js +5 -1
- package/report/generator/tsconfig.json +5 -16
- package/report/renderer/category-renderer.js +58 -5
- package/report/renderer/components.js +25 -5
- package/report/renderer/performance-category-renderer.js +5 -5
- package/report/renderer/pwa-category-renderer.js +10 -0
- package/report/renderer/report-renderer.js +12 -3
- package/report/renderer/report-ui-features.js +1 -4
- package/report/test/renderer/category-renderer-test.js +19 -0
- package/report/tsconfig.json +6 -21
- package/report/types/report-result.d.ts +1 -1
- package/root.js +3 -1
- package/third-party/snyk/snapshot.json +2 -2
- package/tsconfig-all.json +15 -0
- package/tsconfig-base.json +24 -0
- package/tsconfig.json +8 -18
- package/types/artifacts.d.ts +7 -7
- package/types/config.d.ts +1 -1
- package/types/gatherer.d.ts +7 -1
- package/types/lhr/flow.d.ts +0 -1
- package/types/lhr/lhr.d.ts +5 -1
- package/types/lhr/tsconfig.json +4 -14
- package/types/protocol.d.ts +2 -0
- package/types/smokehouse.d.ts +2 -1
- package/dist/report/flow.js +0 -149
- package/dist/report/standalone.js +0 -228
- package/flow-report/test/common-test.tsx +0 -131
- package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
- package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
package/changelog.md
CHANGED
|
@@ -1,3 +1,82 @@
|
|
|
1
|
+
<a name="8.5.0"></a>
|
|
2
|
+
# 8.5.0 (2021-09-21)
|
|
3
|
+
[Full Changelog](https://github.com/GoogleChrome/lighthouse/compare/v8.4.0...v8.5.0)
|
|
4
|
+
|
|
5
|
+
We expect this release to ship in the DevTools of [Chrome 96](https://chromiumdash.appspot.com/schedule), and to PageSpeed Insights within 2 weeks.
|
|
6
|
+
|
|
7
|
+
## New Contributors
|
|
8
|
+
|
|
9
|
+
Thanks to our new contributors 👽🐷🐰🐯🐻!
|
|
10
|
+
|
|
11
|
+
Konstantin Popov @KonstHardy
|
|
12
|
+
Can Umay @canumay
|
|
13
|
+
|
|
14
|
+
## Core
|
|
15
|
+
|
|
16
|
+
* lazy-lcp: fix failureTitle in lcp-lazy-loaded ([#13049](https://github.com/GoogleChrome/lighthouse/pull/13049))
|
|
17
|
+
* tracing: remove cpu_profiler.hires ([#13056](https://github.com/GoogleChrome/lighthouse/pull/13056))
|
|
18
|
+
* tsc: add base tsconfig for config inheritance ([#13072](https://github.com/GoogleChrome/lighthouse/pull/13072))
|
|
19
|
+
* make main tsc compile cacheable ([#13069](https://github.com/GoogleChrome/lighthouse/pull/13069))
|
|
20
|
+
|
|
21
|
+
## ⛏️👷 Fraggle Rock
|
|
22
|
+
|
|
23
|
+
Support for auditing user flows ([#11313](https://github.com/GoogleChrome/lighthouse/issues/11313))
|
|
24
|
+
|
|
25
|
+
* cleanup driver on run completion ([#13062](https://github.com/GoogleChrome/lighthouse/pull/13062))
|
|
26
|
+
* setup emulation and throttling for timespans ([#13058](https://github.com/GoogleChrome/lighthouse/pull/13058))
|
|
27
|
+
* support additionalTraceCategories ([#13030](https://github.com/GoogleChrome/lighthouse/pull/13030))
|
|
28
|
+
* add support for plugins ([#13028](https://github.com/GoogleChrome/lighthouse/pull/13028))
|
|
29
|
+
* move GatherContext to baseArtifacts ([#13033](https://github.com/GoogleChrome/lighthouse/pull/13033))
|
|
30
|
+
* preserve traces on failed page load ([#13027](https://github.com/GoogleChrome/lighthouse/pull/13027))
|
|
31
|
+
* move HostUserAgent/FormFactor back to base artifacts ([#12969](https://github.com/GoogleChrome/lighthouse/pull/12969))
|
|
32
|
+
* use devtools throttling by default in timespan mode ([#13013](https://github.com/GoogleChrome/lighthouse/pull/13013))
|
|
33
|
+
* collect OOPIF network data ([#12992](https://github.com/GoogleChrome/lighthouse/pull/12992))
|
|
34
|
+
* flow: summary sections ([#13086](https://github.com/GoogleChrome/lighthouse/pull/13086))
|
|
35
|
+
* flow: topbar ([#13065](https://github.com/GoogleChrome/lighthouse/pull/13065))
|
|
36
|
+
|
|
37
|
+
## CLI
|
|
38
|
+
|
|
39
|
+
* convert to ES modules ([#13045](https://github.com/GoogleChrome/lighthouse/pull/13045))
|
|
40
|
+
|
|
41
|
+
## Report
|
|
42
|
+
|
|
43
|
+
* make metric value more prominent in table ([#13036](https://github.com/GoogleChrome/lighthouse/pull/13036))
|
|
44
|
+
* 3p-filter: drop for/id as elements are already nested ([#13067](https://github.com/GoogleChrome/lighthouse/pull/13067))
|
|
45
|
+
* add gatherMode option to category score ([#13029](https://github.com/GoogleChrome/lighthouse/pull/13029))
|
|
46
|
+
* add fractional category scores ([#13009](https://github.com/GoogleChrome/lighthouse/pull/13009))
|
|
47
|
+
|
|
48
|
+
## Deps
|
|
49
|
+
|
|
50
|
+
* update to latest @rollup/plugin-typescript ([#13075](https://github.com/GoogleChrome/lighthouse/pull/13075))
|
|
51
|
+
* snyk: update snyk snapshot ([#13019](https://github.com/GoogleChrome/lighthouse/pull/13019))
|
|
52
|
+
|
|
53
|
+
## Clients
|
|
54
|
+
|
|
55
|
+
* lr: bundle smokehouse as commonjs ([#13074](https://github.com/GoogleChrome/lighthouse/pull/13074))
|
|
56
|
+
* add canonical link to viewer and treemap ([#13032](https://github.com/GoogleChrome/lighthouse/pull/13032))
|
|
57
|
+
|
|
58
|
+
## Docs
|
|
59
|
+
|
|
60
|
+
* readme: add Peyk to the list of integrations ([#13055](https://github.com/GoogleChrome/lighthouse/pull/13055))
|
|
61
|
+
|
|
62
|
+
## Tests
|
|
63
|
+
|
|
64
|
+
* add FR integration scenarios ([#13092](https://github.com/GoogleChrome/lighthouse/pull/13092))
|
|
65
|
+
* update SVGOMG expectations ([#13088](https://github.com/GoogleChrome/lighthouse/pull/13088))
|
|
66
|
+
* restore use of latest node 16 in CI ([#13079](https://github.com/GoogleChrome/lighthouse/pull/13079))
|
|
67
|
+
* eslint: trailing commas for import/export ([#13059](https://github.com/GoogleChrome/lighthouse/pull/13059))
|
|
68
|
+
* smokehouse: add flag for test sharding ([#13047](https://github.com/GoogleChrome/lighthouse/pull/13047))
|
|
69
|
+
* smokehouse: convert to ES modules ([#13046](https://github.com/GoogleChrome/lighthouse/pull/13046))
|
|
70
|
+
* fix flaky robots smoke failure ([#13031](https://github.com/GoogleChrome/lighthouse/pull/13031))
|
|
71
|
+
* smoke: upload smokehouse artifacts on failure ([#13010](https://github.com/GoogleChrome/lighthouse/pull/13010))
|
|
72
|
+
|
|
73
|
+
## Misc
|
|
74
|
+
|
|
75
|
+
* build: fix minifyFileTransform stream bug in Node 16 ([#13073](https://github.com/GoogleChrome/lighthouse/pull/13073))
|
|
76
|
+
* fix typo in lighthouse-treemap/app/src/main.js ([#13076](https://github.com/GoogleChrome/lighthouse/pull/13076))
|
|
77
|
+
* proto: add i18n.icuMessagePaths ([#13068](https://github.com/GoogleChrome/lighthouse/pull/13068))
|
|
78
|
+
* remove all FR-COMPAT todos ([#13023](https://github.com/GoogleChrome/lighthouse/pull/13023))
|
|
79
|
+
|
|
1
80
|
<a name="8.4.0"></a>
|
|
2
81
|
# 8.4.0 (2021-09-08)
|
|
3
82
|
[Full Changelog](https://github.com/GoogleChrome/lighthouse/compare/v8.3.0...v8.4.0)
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
--app-font-size: 12px;
|
|
9
9
|
--base-spacing: 16px;
|
|
10
10
|
--category-summary-font-size: 18px;
|
|
11
|
+
--double-base-spacing: calc(var(--base-spacing) * 2);
|
|
11
12
|
--gather-mode-icon-size: 16px;
|
|
12
13
|
--half-base-spacing: calc(var(--base-spacing) / 2);
|
|
14
|
+
--separator-color: var(--color-gray-300);
|
|
13
15
|
--sidebar-flow-step-navigation-font-size: 14px;
|
|
14
16
|
--sidebar-selected-bg-color: #DDEEFF;
|
|
15
17
|
--sidebar-summary-font-size: 14px;
|
|
@@ -17,18 +19,58 @@
|
|
|
17
19
|
--summary-flow-step-label-font-size: 16px;
|
|
18
20
|
--summary-subtitle-font-size: 16px;
|
|
19
21
|
--summary-title-font-size: 32px;
|
|
22
|
+
--topbar-title-font-size: 14px;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
.App {
|
|
23
26
|
display: grid;
|
|
24
|
-
grid-template-areas:
|
|
27
|
+
grid-template-areas:
|
|
28
|
+
"topbar topbar"
|
|
29
|
+
"sidebar content";
|
|
25
30
|
grid-template-columns: min-content auto;
|
|
31
|
+
grid-template-rows: min-content auto;
|
|
26
32
|
height: 100vh;
|
|
27
33
|
max-width: 100vw;
|
|
28
34
|
font-size: var(--app-font-size);
|
|
29
35
|
}
|
|
36
|
+
.App--collapsed {
|
|
37
|
+
grid-template-columns: 0px auto;
|
|
38
|
+
}
|
|
39
|
+
.App--collapsed .Sidebar {
|
|
40
|
+
display: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.Topbar {
|
|
44
|
+
grid-area: topbar;
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
border-bottom: 1px solid var(--separator-color);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.Topbar__menu {
|
|
51
|
+
padding: var(--base-spacing);
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
display: flex;
|
|
54
|
+
-webkit-touch-callout: none;
|
|
55
|
+
-webkit-user-select: none;
|
|
56
|
+
-khtml-user-select: none;
|
|
57
|
+
-moz-user-select: none;
|
|
58
|
+
-ms-user-select: none;
|
|
59
|
+
user-select: none;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.Topbar__logo {
|
|
63
|
+
display: flex;
|
|
64
|
+
margin-right: var(--half-base-spacing);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.Topbar__title {
|
|
68
|
+
font-size: var(--topbar-title-font-size);
|
|
69
|
+
font-weight: bold;
|
|
70
|
+
}
|
|
30
71
|
|
|
31
72
|
.Content {
|
|
73
|
+
grid-area: content;
|
|
32
74
|
overflow-y: auto;
|
|
33
75
|
}
|
|
34
76
|
|
|
@@ -48,59 +90,15 @@
|
|
|
48
90
|
background-color: var(--color-blue-A700);
|
|
49
91
|
}
|
|
50
92
|
|
|
51
|
-
.CategoryRatio {
|
|
52
|
-
justify-self: center;
|
|
53
|
-
display: flex;
|
|
54
|
-
align-items: center;
|
|
55
|
-
justify-content: center;
|
|
56
|
-
font-size: var(--category-summary-font-size);
|
|
57
|
-
min-height: var(--gauge-circle-size);
|
|
58
|
-
min-width: var(--gauge-circle-size);
|
|
59
|
-
text-decoration: none;
|
|
60
|
-
}
|
|
61
|
-
.CategoryRatio::before {
|
|
62
|
-
content: '';
|
|
63
|
-
height: var(--score-icon-size);
|
|
64
|
-
width: var(--score-icon-size);
|
|
65
|
-
margin: var(--score-icon-margin);
|
|
66
|
-
}
|
|
67
|
-
.CategoryRatio--pass {
|
|
68
|
-
color: var(--color-pass);
|
|
69
|
-
}
|
|
70
|
-
.CategoryRatio--pass::before {
|
|
71
|
-
background-color: var(--color-pass);
|
|
72
|
-
border-radius: 50%;
|
|
73
|
-
}
|
|
74
|
-
.CategoryRatio--average {
|
|
75
|
-
color: var(--color-average);
|
|
76
|
-
}
|
|
77
|
-
.CategoryRatio--average::before {
|
|
78
|
-
background-color: var(--color-average);
|
|
79
|
-
}
|
|
80
|
-
.CategoryRatio--fail {
|
|
81
|
-
color: var(--color-fail);
|
|
82
|
-
}
|
|
83
|
-
.CategoryRatio--fail::before {
|
|
84
|
-
border-left: calc(var(--score-icon-size) / 2) solid transparent;
|
|
85
|
-
border-right: calc(var(--score-icon-size) / 2) solid transparent;
|
|
86
|
-
border-bottom: var(--score-icon-size) solid var(--color-fail);
|
|
87
|
-
}
|
|
88
|
-
.CategoryRatio--null {
|
|
89
|
-
color: var(--color-gray-700);
|
|
90
|
-
}
|
|
91
|
-
.CategoryRatio--null::before {
|
|
92
|
-
border-radius: 50%;
|
|
93
|
-
border: 2px solid var(--color-gray-700);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
93
|
.Separator {
|
|
97
94
|
height: 1px;
|
|
98
95
|
width: 100%;
|
|
99
|
-
background-color: var(--color
|
|
96
|
+
background-color: var(--separator-color);
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
.Sidebar {
|
|
103
|
-
|
|
100
|
+
grid-area: sidebar;
|
|
101
|
+
border-right: 1px solid var(--separator-color);
|
|
104
102
|
}
|
|
105
103
|
.Sidebar a {
|
|
106
104
|
color: var(--color-gray-800);
|
|
@@ -192,14 +190,21 @@
|
|
|
192
190
|
}
|
|
193
191
|
|
|
194
192
|
.Summary {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
193
|
+
display: grid;
|
|
194
|
+
grid-template-columns: minmax(5%, 1fr) auto minmax(5%, 1fr);
|
|
195
|
+
justify-content: start;
|
|
196
|
+
width: 100%;
|
|
197
|
+
}
|
|
198
|
+
.Summary > * {
|
|
199
|
+
grid-column: 2;
|
|
200
|
+
}
|
|
201
|
+
.Summary > .Separator {
|
|
202
|
+
grid-column: 1 / span 3;
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
.SummaryHeader {
|
|
202
|
-
margin: var(--base-spacing)
|
|
206
|
+
margin: calc(var(--base-spacing) * 3) 0px;
|
|
207
|
+
width: 100%;
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
.SummaryHeader__title {
|
|
@@ -211,12 +216,26 @@
|
|
|
211
216
|
font-size: var(--summary-subtitle-font-size);
|
|
212
217
|
}
|
|
213
218
|
|
|
219
|
+
.SummarySectionHeader {
|
|
220
|
+
margin-top: var(--double-base-spacing);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.SummarySectionHeader__content {
|
|
224
|
+
margin: var(--base-spacing) 0px;
|
|
225
|
+
}
|
|
226
|
+
|
|
214
227
|
.SummaryFlow {
|
|
215
228
|
width: 100%;
|
|
229
|
+
max-width: max-content;
|
|
216
230
|
display: grid;
|
|
217
231
|
grid-auto-rows: min-content;
|
|
218
232
|
grid-template-columns: min-content min-content 4fr 1fr 1fr 1fr 1fr;
|
|
219
233
|
align-items: center;
|
|
234
|
+
margin: var(--base-spacing) 0px;
|
|
235
|
+
}
|
|
236
|
+
.SummaryFlow .lh-fraction__content {
|
|
237
|
+
padding: 0px;
|
|
238
|
+
min-width: unset;
|
|
220
239
|
}
|
|
221
240
|
|
|
222
241
|
/* Hide top segment of sidebar flow */
|
|
@@ -259,11 +278,18 @@
|
|
|
259
278
|
}
|
|
260
279
|
|
|
261
280
|
.SummaryFlowStep__label {
|
|
281
|
+
grid-column: 3;
|
|
282
|
+
margin: var(--half-base-spacing);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.SummaryFlowStep__mode {
|
|
286
|
+
color: var(--color-gray-700);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.SummaryFlowStep__link {
|
|
262
290
|
font-size: var(--summary-flow-step-label-font-size);
|
|
263
291
|
color: var(--color-gray-800);
|
|
264
292
|
text-decoration: underline;
|
|
265
|
-
grid-column: 3;
|
|
266
|
-
margin: var(--half-base-spacing);
|
|
267
293
|
}
|
|
268
294
|
|
|
269
295
|
.SummaryCategory {
|
|
@@ -282,7 +308,8 @@
|
|
|
282
308
|
align-items: center;
|
|
283
309
|
justify-content: center;
|
|
284
310
|
padding: var(--half-base-spacing);
|
|
285
|
-
background-color: var(--color-gray-
|
|
311
|
+
background-color: var(--color-gray-100);
|
|
312
|
+
border-top: 1px solid var(--color-gray-300);
|
|
286
313
|
text-align: center;
|
|
287
314
|
}
|
|
288
315
|
.SummaryNavigationHeader__url {
|
|
@@ -290,14 +317,11 @@
|
|
|
290
317
|
text-align: left;
|
|
291
318
|
}
|
|
292
319
|
|
|
293
|
-
.
|
|
320
|
+
.SummaryFlowStep__separator {
|
|
294
321
|
display: contents;
|
|
295
322
|
}
|
|
296
|
-
|
|
297
|
-
.SummaryFlowStep__divider--line {
|
|
323
|
+
.SummaryFlowStep__separator > .Separator {
|
|
298
324
|
grid-column-end: span 5;
|
|
299
|
-
height: 1px;
|
|
300
|
-
background-color: var(--color-gray-300);
|
|
301
325
|
}
|
|
302
326
|
|
|
303
327
|
.SummaryCategory__null {
|
package/flow-report/src/app.tsx
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
|
+
import {useState} from 'preact/hooks';
|
|
8
9
|
|
|
9
10
|
import {ReportRendererProvider} from './wrappers/report-renderer';
|
|
10
11
|
import {Sidebar} from './sidebar/sidebar';
|
|
11
12
|
import {Summary} from './summary/summary';
|
|
12
|
-
import {FlowResultContext, useCurrentLhr} from './util';
|
|
13
|
+
import {classNames, FlowResultContext, useCurrentLhr} from './util';
|
|
13
14
|
import {Report} from './wrappers/report';
|
|
15
|
+
import {Topbar} from './topbar';
|
|
14
16
|
|
|
15
17
|
const Content: FunctionComponent = () => {
|
|
16
18
|
const currentLhr = useCurrentLhr();
|
|
@@ -27,10 +29,12 @@ const Content: FunctionComponent = () => {
|
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
export const App: FunctionComponent<{flowResult: LH.FlowResult}> = ({flowResult}) => {
|
|
32
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
30
33
|
return (
|
|
31
34
|
<FlowResultContext.Provider value={flowResult}>
|
|
32
35
|
<ReportRendererProvider>
|
|
33
|
-
<div className=
|
|
36
|
+
<div className={classNames('App', {'App--collapsed': collapsed})}>
|
|
37
|
+
<Topbar onMenuClick={() => setCollapsed(c => !c)} />
|
|
34
38
|
<Sidebar/>
|
|
35
39
|
<Content/>
|
|
36
40
|
</div>
|
|
@@ -6,49 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
8
|
|
|
9
|
-
import {Util} from '../../report/renderer/util';
|
|
10
9
|
import {NavigationIcon, SnapshotIcon, TimespanIcon} from './icons';
|
|
11
10
|
|
|
12
|
-
/**
|
|
13
|
-
* Summarizes the category as a ratio of passed audits to total audits.
|
|
14
|
-
* The rating color and icon are calculated from the passed/total ratio, not the category score.
|
|
15
|
-
* A category will be given a null rating and color if none of its audits are weighted.
|
|
16
|
-
*/
|
|
17
|
-
export const CategoryRatio: FunctionComponent<{
|
|
18
|
-
category: LH.ReportResult.Category,
|
|
19
|
-
audits: LH.Result['audits'],
|
|
20
|
-
href: string,
|
|
21
|
-
}> = ({category, audits, href}) => {
|
|
22
|
-
const numAudits = category.auditRefs.length;
|
|
23
|
-
|
|
24
|
-
let numPassed = 0;
|
|
25
|
-
let totalWeight = 0;
|
|
26
|
-
for (const auditRef of category.auditRefs) {
|
|
27
|
-
totalWeight += auditRef.weight;
|
|
28
|
-
const audit = audits[auditRef.id];
|
|
29
|
-
if (!audit) {
|
|
30
|
-
console.warn(`Could not find score for audit '${auditRef.id}', treating as failed.`);
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
if (Util.showAsPassed(audit)) numPassed++;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const ratio = numPassed / numAudits;
|
|
37
|
-
let rating = Util.calculateRating(ratio);
|
|
38
|
-
|
|
39
|
-
// If none of the available audits can affect the score, a rating isn't useful.
|
|
40
|
-
// The flow report should display the ratio with neutral icon and coloring in this case.
|
|
41
|
-
if (totalWeight === 0) {
|
|
42
|
-
rating = 'null';
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<a href={href} className={`CategoryRatio CategoryRatio--${rating}`} data-testid="CategoryRatio">
|
|
47
|
-
{`${numPassed}/${numAudits}`}
|
|
48
|
-
</a>
|
|
49
|
-
);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
11
|
export const Separator: FunctionComponent = () => {
|
|
53
12
|
return <div className="Separator" role="separator"></div>;
|
|
54
13
|
};
|
|
@@ -94,3 +94,14 @@ export const CpuIcon: FunctionComponent = () => {
|
|
|
94
94
|
</svg>
|
|
95
95
|
);
|
|
96
96
|
};
|
|
97
|
+
|
|
98
|
+
export const HamburgerIcon: FunctionComponent = () => {
|
|
99
|
+
return (
|
|
100
|
+
<svg viewBox="0 0 18 12" width="18" height="12" role="img">
|
|
101
|
+
<rect width="18" height="2"></rect>
|
|
102
|
+
<rect y="5" width="18" height="2"></rect>
|
|
103
|
+
<rect y="10" width="18" height="2"></rect>
|
|
104
|
+
</svg>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
@@ -7,14 +7,18 @@
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
8
|
import {useMemo} from 'preact/hooks';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import {FlowSegment} from '../common';
|
|
12
|
-
import {CategoryRatio} from '../common';
|
|
10
|
+
import {FlowSegment, Separator} from '../common';
|
|
13
11
|
import {getScreenDimensions, getScreenshot, useDerivedStepNames, useFlowResult} from '../util';
|
|
14
12
|
import {Util} from '../../../report/renderer/util';
|
|
13
|
+
import {CategoryScore} from '../wrappers/category-score';
|
|
15
14
|
|
|
16
15
|
const DISPLAYED_CATEGORIES = ['performance', 'accessibility', 'best-practices', 'seo'];
|
|
17
16
|
const THUMBNAIL_WIDTH = 50;
|
|
17
|
+
const MODE_DESCRIPTIONS: Record<LH.Result.GatherMode, string> = {
|
|
18
|
+
'navigation': 'Page load',
|
|
19
|
+
'timespan': 'User interactions',
|
|
20
|
+
'snapshot': 'Captured state of page',
|
|
21
|
+
};
|
|
18
22
|
|
|
19
23
|
const SummaryNavigationHeader: FunctionComponent<{url: string}> = ({url}) => {
|
|
20
24
|
return (
|
|
@@ -30,27 +34,19 @@ const SummaryNavigationHeader: FunctionComponent<{url: string}> = ({url}) => {
|
|
|
30
34
|
};
|
|
31
35
|
|
|
32
36
|
const SummaryCategory: FunctionComponent<{
|
|
33
|
-
gatherMode: LH.Result.GatherMode,
|
|
34
|
-
audits: LH.ReportResult['audits'],
|
|
35
37
|
category: LH.ReportResult.Category|undefined,
|
|
36
38
|
href: string,
|
|
37
|
-
|
|
39
|
+
gatherMode: LH.Result.GatherMode,
|
|
40
|
+
}> = ({category, href, gatherMode}) => {
|
|
38
41
|
return (
|
|
39
42
|
<div className="SummaryCategory">
|
|
40
43
|
{
|
|
41
44
|
category ?
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/> :
|
|
48
|
-
<CategoryRatio
|
|
49
|
-
category={category}
|
|
50
|
-
audits={audits}
|
|
51
|
-
href={href}
|
|
52
|
-
/>
|
|
53
|
-
) :
|
|
45
|
+
<CategoryScore
|
|
46
|
+
category={category}
|
|
47
|
+
href={href}
|
|
48
|
+
gatherMode={gatherMode}
|
|
49
|
+
/> :
|
|
54
50
|
<div
|
|
55
51
|
className="SummaryCategory__null"
|
|
56
52
|
data-testid="SummaryCategory__null"
|
|
@@ -68,7 +64,6 @@ export const SummaryFlowStep: FunctionComponent<{
|
|
|
68
64
|
label: string,
|
|
69
65
|
hashIndex: number,
|
|
70
66
|
}> = ({lhr, label, hashIndex}) => {
|
|
71
|
-
// TODO(FR-COMPAT): Store report results globally.
|
|
72
67
|
const reportResult = useMemo(() => Util.prepareReportResult(lhr), [lhr]);
|
|
73
68
|
|
|
74
69
|
const screenshot = reportResult.gatherMode !== 'timespan' ? getScreenshot(reportResult) : null;
|
|
@@ -82,9 +77,9 @@ export const SummaryFlowStep: FunctionComponent<{
|
|
|
82
77
|
{
|
|
83
78
|
lhr.gatherMode === 'navigation' || hashIndex === 0 ?
|
|
84
79
|
<SummaryNavigationHeader url={lhr.finalUrl}/> :
|
|
85
|
-
<div className="
|
|
80
|
+
<div className="SummaryFlowStep__separator">
|
|
86
81
|
<FlowSegment/>
|
|
87
|
-
<
|
|
82
|
+
<Separator/>
|
|
88
83
|
</div>
|
|
89
84
|
}
|
|
90
85
|
<img
|
|
@@ -94,15 +89,17 @@ export const SummaryFlowStep: FunctionComponent<{
|
|
|
94
89
|
style={{width: THUMBNAIL_WIDTH, maxHeight: thumbnailHeight}}
|
|
95
90
|
/>
|
|
96
91
|
<FlowSegment mode={lhr.gatherMode}/>
|
|
97
|
-
<
|
|
92
|
+
<div className="SummaryFlowStep__label">
|
|
93
|
+
<div className="SummaryFlowStep__mode">{MODE_DESCRIPTIONS[lhr.gatherMode]}</div>
|
|
94
|
+
<a className="SummaryFlowStep__link" href={`#index=${hashIndex}`}>{label}</a>
|
|
95
|
+
</div>
|
|
98
96
|
{
|
|
99
97
|
DISPLAYED_CATEGORIES.map(c => (
|
|
100
98
|
<SummaryCategory
|
|
101
99
|
key={c}
|
|
102
|
-
gatherMode={reportResult.gatherMode}
|
|
103
100
|
category={reportResult.categories[c]}
|
|
104
|
-
audits={reportResult.audits}
|
|
105
101
|
href={`#index=${hashIndex}&anchor=${c}`}
|
|
102
|
+
gatherMode={lhr.gatherMode}
|
|
106
103
|
/>
|
|
107
104
|
))
|
|
108
105
|
}
|
|
@@ -153,7 +150,6 @@ export const SummaryHeader: FunctionComponent = () => {
|
|
|
153
150
|
}
|
|
154
151
|
}
|
|
155
152
|
|
|
156
|
-
// TODO(FR-COMPAT): Pluralize UI strings.
|
|
157
153
|
const subtitleCounts = [];
|
|
158
154
|
if (numNavigation) subtitleCounts.push(`${numNavigation} navigation reports`);
|
|
159
155
|
if (numTimespan) subtitleCounts.push(`${numTimespan} timespan reports`);
|
|
@@ -168,10 +164,21 @@ export const SummaryHeader: FunctionComponent = () => {
|
|
|
168
164
|
);
|
|
169
165
|
};
|
|
170
166
|
|
|
167
|
+
const SummarySectionHeader: FunctionComponent = ({children}) => {
|
|
168
|
+
return (
|
|
169
|
+
<div className="SummarySectionHeader">
|
|
170
|
+
<div className="SummarySectionHeader__content">{children}</div>
|
|
171
|
+
<Separator/>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
171
176
|
export const Summary: FunctionComponent = () => {
|
|
172
177
|
return (
|
|
173
178
|
<div className="Summary" data-testid="Summary">
|
|
174
179
|
<SummaryHeader/>
|
|
180
|
+
<Separator/>
|
|
181
|
+
<SummarySectionHeader>ALL REPORTS</SummarySectionHeader>
|
|
175
182
|
<SummaryFlow/>
|
|
176
183
|
</div>
|
|
177
184
|
);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {FunctionComponent, JSX} from 'preact';
|
|
8
|
+
|
|
9
|
+
import {HamburgerIcon} from './icons';
|
|
10
|
+
|
|
11
|
+
/* eslint-disable max-len */
|
|
12
|
+
const Logo: FunctionComponent = () => {
|
|
13
|
+
return (
|
|
14
|
+
<svg height="24" width="24" viewBox="0 0 24 24" role="img">
|
|
15
|
+
<defs>
|
|
16
|
+
<linearGradient x1="57.456%" y1="13.086%" x2="18.259%" y2="72.322%" id="Topbar__logo--a">
|
|
17
|
+
<stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
|
|
18
|
+
<stop stop-color="#262626" stop-opacity="0" offset="100%"/>
|
|
19
|
+
</linearGradient>
|
|
20
|
+
<linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="Topbar__logo--b">
|
|
21
|
+
<stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
|
|
22
|
+
<stop stop-color="#262626" stop-opacity="0" offset="100%"/>
|
|
23
|
+
</linearGradient>
|
|
24
|
+
<linearGradient x1="58.764%" y1="65.756%" x2="36.939%" y2="50.14%" id="Topbar__logo--c">
|
|
25
|
+
<stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
|
|
26
|
+
<stop stop-color="#262626" stop-opacity="0" offset="100%"/>
|
|
27
|
+
</linearGradient>
|
|
28
|
+
<linearGradient x1="41.635%" y1="20.358%" x2="72.863%" y2="85.424%" id="Topbar__logo--d">
|
|
29
|
+
<stop stop-color="#FFF" stop-opacity=".1" offset="0%"/>
|
|
30
|
+
<stop stop-color="#FFF" stop-opacity="0" offset="100%"/>
|
|
31
|
+
</linearGradient>
|
|
32
|
+
</defs>
|
|
33
|
+
<g fill="none" fill-rule="evenodd">
|
|
34
|
+
<path d="M12 3l4.125 2.625v3.75H18v2.25h-1.688l1.5 9.375H6.188l1.5-9.375H6v-2.25h1.875V5.648L12 3zm2.201 9.938L9.54 14.633 9 18.028l5.625-2.062-.424-3.028zM12.005 5.67l-1.88 1.207v2.498h3.75V6.86l-1.87-1.19z" fill="#F44B21"/>
|
|
35
|
+
<path fill="#FFF" d="M14.201 12.938L9.54 14.633 9 18.028l5.625-2.062z"/>
|
|
36
|
+
<path d="M6 18c-2.042 0-3.95-.01-5.813 0l1.5-9.375h4.326L6 18z" fill="url(#Topbar__logo--a)" fill-rule="nonzero" transform="translate(6 3)"/>
|
|
37
|
+
<path fill="#FFF176" fill-rule="nonzero" d="M13.875 9.375v-2.56l-1.87-1.19-1.88 1.207v2.543z"/>
|
|
38
|
+
<path fill="url(#Topbar__logo--b)" fill-rule="nonzero" d="M0 6.375h6v2.25H0z" transform="translate(6 3)"/>
|
|
39
|
+
<path fill="url(#Topbar__logo--c)" fill-rule="nonzero" d="M6 6.375H1.875v-3.75L6 0z" transform="translate(6 3)"/>
|
|
40
|
+
<path fill="url(#Topbar__logo--d)" fill-rule="nonzero" d="M6 0l4.125 2.625v3.75H12v2.25h-1.688l1.5 9.375H.188l1.5-9.375H0v-2.25h1.875V2.648z" transform="translate(6 3)"/>
|
|
41
|
+
</g>
|
|
42
|
+
</svg>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
/* eslint-enable max-len */
|
|
46
|
+
|
|
47
|
+
export const Topbar: FunctionComponent<{onMenuClick: JSX.MouseEventHandler<HTMLDivElement>}> =
|
|
48
|
+
({onMenuClick}) => {
|
|
49
|
+
return (
|
|
50
|
+
<div className="Topbar">
|
|
51
|
+
<div className="Topbar__menu" onClick={onMenuClick} role="button">
|
|
52
|
+
<HamburgerIcon/>
|
|
53
|
+
</div>
|
|
54
|
+
<div className="Topbar__logo">
|
|
55
|
+
<Logo/>
|
|
56
|
+
</div>
|
|
57
|
+
<div className="Topbar__title">Lighthouse User Flow Report</div>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
package/flow-report/src/util.ts
CHANGED
|
@@ -9,17 +9,23 @@ import {useEffect, useLayoutEffect, useRef} from 'preact/hooks';
|
|
|
9
9
|
|
|
10
10
|
import {useReportRenderer} from './report-renderer';
|
|
11
11
|
|
|
12
|
-
export const
|
|
13
|
-
|
|
12
|
+
export const CategoryScore: FunctionComponent<{
|
|
13
|
+
category: LH.ReportResult.Category,
|
|
14
|
+
href: string,
|
|
15
|
+
gatherMode: LH.Result.GatherMode,
|
|
16
|
+
}> = ({category, href, gatherMode}) => {
|
|
14
17
|
const {categoryRenderer} = useReportRenderer();
|
|
15
18
|
const ref = useRef<HTMLDivElement>(null);
|
|
16
19
|
|
|
17
20
|
useLayoutEffect(() => {
|
|
18
|
-
const el = categoryRenderer.
|
|
21
|
+
const el = categoryRenderer.renderCategoryScore(category, {}, {gatherMode});
|
|
19
22
|
|
|
20
23
|
// Category label is displayed in the navigation header.
|
|
21
|
-
const label = el.querySelector('.lh-gauge__label');
|
|
24
|
+
const label = el.querySelector('.lh-gauge__label,.lh-fraction__label');
|
|
22
25
|
if (label) label.remove();
|
|
26
|
+
// Background is displayed in individual reports, but not on the summary page.
|
|
27
|
+
const bg = el.querySelector('.lh-fraction__background');
|
|
28
|
+
if (bg) bg.remove();
|
|
23
29
|
|
|
24
30
|
if (ref.current) ref.current.append(el);
|
|
25
31
|
return () => {
|
|
@@ -35,6 +41,6 @@ export const Gauge: FunctionComponent<{category: LH.ReportResult.Category, href:
|
|
|
35
41
|
}, [href]);
|
|
36
42
|
|
|
37
43
|
return (
|
|
38
|
-
<div ref={ref} data-testid="
|
|
44
|
+
<div ref={ref} data-testid="CategoryScore"/>
|
|
39
45
|
);
|
|
40
46
|
};
|
|
@@ -62,7 +62,7 @@ describe('SummaryFlowStep', () => {
|
|
|
62
62
|
const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
|
|
63
63
|
expect(screenshot.src).toMatch(/data:image\/jpeg;base64/);
|
|
64
64
|
|
|
65
|
-
const gauges = root.getAllByTestId('
|
|
65
|
+
const gauges = root.getAllByTestId('CategoryScore');
|
|
66
66
|
expect(gauges).toHaveLength(4);
|
|
67
67
|
|
|
68
68
|
const links = root.getAllByRole('link') as HTMLAnchorElement[];
|
|
@@ -90,7 +90,7 @@ describe('SummaryFlowStep', () => {
|
|
|
90
90
|
expect(screenshot.src).toBeFalsy();
|
|
91
91
|
|
|
92
92
|
expect(root.getByTestId('SummaryCategory__null'));
|
|
93
|
-
const gauges = root.getAllByTestId('
|
|
93
|
+
const gauges = root.getAllByTestId('CategoryScore');
|
|
94
94
|
expect(gauges).toHaveLength(3);
|
|
95
95
|
|
|
96
96
|
const links = root.getAllByRole('link') as HTMLAnchorElement[];
|
|
@@ -117,7 +117,7 @@ describe('SummaryFlowStep', () => {
|
|
|
117
117
|
const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
|
|
118
118
|
expect(screenshot.src).toMatch(/data:image\/jpeg;base64/);
|
|
119
119
|
|
|
120
|
-
const gauges = root.getAllByTestId('
|
|
120
|
+
const gauges = root.getAllByTestId('CategoryScore');
|
|
121
121
|
expect(gauges).toHaveLength(4);
|
|
122
122
|
|
|
123
123
|
const links = root.getAllByRole('link') as HTMLAnchorElement[];
|