lighthouse 11.7.0-dev.20240408 → 11.7.0-dev.20240410
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/cli/cli-flags.js +3 -3
- package/cli/test/smokehouse/config/exclusions.js +1 -0
- package/cli/test/smokehouse/core-tests.js +4 -16
- package/cli/test/smokehouse/frontends/smokehouse-bin.js +2 -2
- package/core/audits/redirects-http.d.ts +19 -0
- package/core/audits/redirects-http.js +75 -0
- package/core/config/default-config.js +10 -52
- package/core/gather/driver/target-manager.js +1 -1
- package/core/gather/driver/wait-for-condition.js +2 -3
- package/core/gather/driver.js +1 -0
- package/core/gather/session.d.ts +8 -0
- package/core/gather/session.js +12 -0
- package/core/lib/lantern/network-node.js +28 -4
- package/core/runner.js +18 -23
- package/dist/report/bundle.esm.js +11 -95
- package/dist/report/flow.js +16 -100
- package/dist/report/standalone.js +12 -96
- package/flow-report/src/help-dialog.tsx +0 -1
- package/flow-report/src/i18n/i18n.d.ts +0 -4
- package/flow-report/src/i18n/ui-strings.d.ts +0 -1
- package/flow-report/src/i18n/ui-strings.js +0 -2
- package/package.json +1 -1
- package/readme.md +2 -2
- package/report/assets/styles.css +1 -43
- package/report/assets/templates.html +0 -95
- package/report/renderer/components.d.ts +2 -2
- package/report/renderer/components.js +2 -103
- package/report/renderer/report-renderer.js +2 -12
- package/report/renderer/report-ui-features.js +1 -1
- package/report/renderer/report-utils.d.ts +0 -1
- package/report/renderer/report-utils.js +0 -3
- package/shared/localization/locales/ar-XB.json +0 -174
- package/shared/localization/locales/ar.json +0 -174
- package/shared/localization/locales/bg.json +0 -174
- package/shared/localization/locales/ca.json +0 -174
- package/shared/localization/locales/cs.json +0 -174
- package/shared/localization/locales/da.json +0 -174
- package/shared/localization/locales/de.json +0 -174
- package/shared/localization/locales/el.json +0 -174
- package/shared/localization/locales/en-GB.json +0 -174
- package/shared/localization/locales/en-US.json +9 -177
- package/shared/localization/locales/en-XA.json +0 -174
- package/shared/localization/locales/en-XL.json +9 -177
- package/shared/localization/locales/es-419.json +0 -174
- package/shared/localization/locales/es.json +0 -174
- package/shared/localization/locales/fi.json +0 -174
- package/shared/localization/locales/fil.json +0 -174
- package/shared/localization/locales/fr.json +0 -174
- package/shared/localization/locales/he.json +0 -174
- package/shared/localization/locales/hi.json +0 -174
- package/shared/localization/locales/hr.json +0 -174
- package/shared/localization/locales/hu.json +0 -174
- package/shared/localization/locales/id.json +0 -174
- package/shared/localization/locales/it.json +0 -174
- package/shared/localization/locales/ja.json +0 -174
- package/shared/localization/locales/ko.json +0 -174
- package/shared/localization/locales/lt.json +0 -174
- package/shared/localization/locales/lv.json +0 -174
- package/shared/localization/locales/nl.json +0 -174
- package/shared/localization/locales/no.json +0 -174
- package/shared/localization/locales/pl.json +0 -174
- package/shared/localization/locales/pt-PT.json +0 -174
- package/shared/localization/locales/pt.json +0 -174
- package/shared/localization/locales/ro.json +0 -174
- package/shared/localization/locales/ru.json +0 -174
- package/shared/localization/locales/sk.json +0 -174
- package/shared/localization/locales/sl.json +0 -174
- package/shared/localization/locales/sr-Latn.json +0 -174
- package/shared/localization/locales/sr.json +0 -174
- package/shared/localization/locales/sv.json +0 -174
- package/shared/localization/locales/ta.json +0 -174
- package/shared/localization/locales/te.json +0 -174
- package/shared/localization/locales/th.json +0 -174
- package/shared/localization/locales/tr.json +0 -174
- package/shared/localization/locales/uk.json +0 -174
- package/shared/localization/locales/vi.json +0 -174
- package/shared/localization/locales/zh-HK.json +0 -174
- package/shared/localization/locales/zh-TW.json +0 -174
- package/shared/localization/locales/zh.json +0 -174
- package/types/artifacts.d.ts +0 -27
- package/types/audit.d.ts +0 -10
- package/types/gatherer.d.ts +1 -0
- package/types/internal/smokehouse.d.ts +1 -1
- package/core/audits/content-width.d.ts +0 -17
- package/core/audits/content-width.js +0 -76
- package/core/audits/installable-manifest.d.ts +0 -111
- package/core/audits/installable-manifest.js +0 -248
- package/core/audits/manual/pwa-cross-browser.d.ts +0 -12
- package/core/audits/manual/pwa-cross-browser.js +0 -40
- package/core/audits/manual/pwa-each-page-has-url.d.ts +0 -12
- package/core/audits/manual/pwa-each-page-has-url.js +0 -38
- package/core/audits/manual/pwa-page-transitions.d.ts +0 -12
- package/core/audits/manual/pwa-page-transitions.js +0 -38
- package/core/audits/maskable-icon.d.ts +0 -25
- package/core/audits/maskable-icon.js +0 -70
- package/core/audits/multi-check-audit.d.ts +0 -28
- package/core/audits/multi-check-audit.js +0 -82
- package/core/audits/splash-screen.d.ts +0 -37
- package/core/audits/splash-screen.js +0 -98
- package/core/audits/themed-omnibox.d.ts +0 -42
- package/core/audits/themed-omnibox.js +0 -102
- package/core/computed/manifest-values.d.ts +0 -24
- package/core/computed/manifest-values.js +0 -136
- package/core/gather/gatherers/installability-errors.d.ts +0 -17
- package/core/gather/gatherers/installability-errors.js +0 -56
- package/core/gather/gatherers/web-app-manifest.d.ts +0 -32
- package/core/gather/gatherers/web-app-manifest.js +0 -106
- package/report/renderer/pwa-category-renderer.d.ts +0 -55
- package/report/renderer/pwa-category-renderer.js +0 -184
- package/third-party/chromium-synchronization/installability-errors-test.js +0 -79
package/cli/cli-flags.js
CHANGED
|
@@ -53,8 +53,8 @@ function getYargsParser(manualArgv) {
|
|
|
53
53
|
'lighthouse <url> --extra-headers=./path/to/file.json',
|
|
54
54
|
'Path to JSON file of HTTP Header key/value pairs to send in requests')
|
|
55
55
|
.example(
|
|
56
|
-
'lighthouse <url> --only-categories=performance,
|
|
57
|
-
'Only run the specified categories. Available categories: accessibility, best-practices, performance,
|
|
56
|
+
'lighthouse <url> --only-categories=performance,seo',
|
|
57
|
+
'Only run the specified categories. Available categories: accessibility, best-practices, performance, seo')
|
|
58
58
|
|
|
59
59
|
// We only have the single string positional argument, the url.
|
|
60
60
|
.option('_', {
|
|
@@ -188,7 +188,7 @@ function getYargsParser(manualArgv) {
|
|
|
188
188
|
array: true,
|
|
189
189
|
type: 'string',
|
|
190
190
|
coerce: splitCommaSeparatedValues,
|
|
191
|
-
describe: 'Only run the specified categories. Available categories: accessibility, best-practices, performance,
|
|
191
|
+
describe: 'Only run the specified categories. Available categories: accessibility, best-practices, performance, seo',
|
|
192
192
|
},
|
|
193
193
|
'skip-audits': {
|
|
194
194
|
array: true,
|
|
@@ -20,6 +20,7 @@ const exclusions = {
|
|
|
20
20
|
'redirects-client-paint-server', 'redirects-multiple-server',
|
|
21
21
|
'redirects-single-server', 'redirects-single-client',
|
|
22
22
|
'redirects-history-push-state', 'redirects-scripts',
|
|
23
|
+
'redirects-http',
|
|
23
24
|
// Disabled because these tests use settings that cannot be fully configured in
|
|
24
25
|
// DevTools (e.g. throttling method "provided").
|
|
25
26
|
'metrics-tricky-tti', 'metrics-tricky-tti-late-fcp', 'screenshot',
|
|
@@ -13,6 +13,7 @@ import dbw from './test-definitions/dobetterweb.js';
|
|
|
13
13
|
import errorsExpiredSsl from './test-definitions/errors-expired-ssl.js';
|
|
14
14
|
import errorsIframeExpiredSsl from './test-definitions/errors-iframe-expired-ssl.js';
|
|
15
15
|
import errorsInfiniteLoop from './test-definitions/errors-infinite-loop.js';
|
|
16
|
+
import fontSize from './test-definitions/font-size.js';
|
|
16
17
|
import formsAutoComplete from './test-definitions/forms-autocomplete.js';
|
|
17
18
|
import fpsMax from './test-definitions/fps-max.js';
|
|
18
19
|
import fpsMaxPassive from './test-definitions/fps-max-passive.js';
|
|
@@ -31,9 +32,6 @@ import metricsDelayedFcp from './test-definitions/metrics-delayed-fcp.js';
|
|
|
31
32
|
import metricsDelayedLcp from './test-definitions/metrics-delayed-lcp.js';
|
|
32
33
|
import metricsTrickyTti from './test-definitions/metrics-tricky-tti.js';
|
|
33
34
|
import metricsTrickyTtiLateFcp from './test-definitions/metrics-tricky-tti-late-fcp.js';
|
|
34
|
-
import offlineOnlineOnly from './test-definitions/offline-online-only.js';
|
|
35
|
-
import offlineReady from './test-definitions/offline-ready.js';
|
|
36
|
-
import offlineSwBroken from './test-definitions/offline-sw-broken.js';
|
|
37
35
|
import oopifRequests from './test-definitions/oopif-requests.js';
|
|
38
36
|
import oopifScripts from './test-definitions/oopif-scripts.js';
|
|
39
37
|
import perfBudgets from './test-definitions/perf-budgets.js';
|
|
@@ -45,13 +43,9 @@ import perfFonts from './test-definitions/perf-fonts.js';
|
|
|
45
43
|
import perfFrameMetrics from './test-definitions/perf-frame-metrics.js';
|
|
46
44
|
import perfPreload from './test-definitions/perf-preload.js';
|
|
47
45
|
import perfTraceElements from './test-definitions/perf-trace-elements.js';
|
|
48
|
-
import pwaAirhorner from './test-definitions/pwa-airhorner.js';
|
|
49
|
-
import pwaCaltrain from './test-definitions/pwa-caltrain.js';
|
|
50
|
-
import pwaChromestatus from './test-definitions/pwa-chromestatus.js';
|
|
51
|
-
import pwaRocks from './test-definitions/pwa-rocks.js';
|
|
52
|
-
import pwaSvgomg from './test-definitions/pwa-svgomg.js';
|
|
53
46
|
import redirectsClientPaintServer from './test-definitions/redirects-client-paint-server.js';
|
|
54
47
|
import redirectsHistoryPushState from './test-definitions/redirects-history-push-state.js';
|
|
48
|
+
import redirectsHttp from './test-definitions/redirects-http.js';
|
|
55
49
|
import redirectsMultipleServer from './test-definitions/redirects-multiple-server.js';
|
|
56
50
|
import redirectsScripts from './test-definitions/redirects-scripts.js';
|
|
57
51
|
import redirectsSelf from './test-definitions/redirects-self.js';
|
|
@@ -77,6 +71,7 @@ const smokeTests = [
|
|
|
77
71
|
errorsExpiredSsl,
|
|
78
72
|
errorsIframeExpiredSsl,
|
|
79
73
|
errorsInfiniteLoop,
|
|
74
|
+
fontSize,
|
|
80
75
|
formsAutoComplete,
|
|
81
76
|
fpsMax,
|
|
82
77
|
fpsMaxPassive,
|
|
@@ -95,9 +90,6 @@ const smokeTests = [
|
|
|
95
90
|
metricsDelayedLcp,
|
|
96
91
|
metricsTrickyTti,
|
|
97
92
|
metricsTrickyTtiLateFcp,
|
|
98
|
-
offlineOnlineOnly,
|
|
99
|
-
offlineReady,
|
|
100
|
-
offlineSwBroken,
|
|
101
93
|
oopifRequests,
|
|
102
94
|
oopifScripts,
|
|
103
95
|
perfBudgets,
|
|
@@ -109,13 +101,9 @@ const smokeTests = [
|
|
|
109
101
|
perfFrameMetrics,
|
|
110
102
|
perfPreload,
|
|
111
103
|
perfTraceElements,
|
|
112
|
-
pwaAirhorner,
|
|
113
|
-
pwaCaltrain,
|
|
114
|
-
pwaChromestatus,
|
|
115
|
-
pwaRocks,
|
|
116
|
-
pwaSvgomg,
|
|
117
104
|
redirectsClientPaintServer,
|
|
118
105
|
redirectsHistoryPushState,
|
|
106
|
+
redirectsHttp,
|
|
119
107
|
redirectsMultipleServer,
|
|
120
108
|
redirectsScripts,
|
|
121
109
|
redirectsSelf,
|
|
@@ -59,7 +59,7 @@ function getDefinitionsToRun(allTestDefns, requestedIds, excludedTests) {
|
|
|
59
59
|
} else {
|
|
60
60
|
smokes = allTestDefns.filter(test => {
|
|
61
61
|
// Include all tests that *include* requested id.
|
|
62
|
-
// e.g. a requested '
|
|
62
|
+
// e.g. a requested 'perf' will match 'perf-preload', 'perf-trace-elements', etc
|
|
63
63
|
return requestedIds.some(requestedId => test.id.includes(requestedId));
|
|
64
64
|
});
|
|
65
65
|
console.log(`Running ONLY smoketests for: ${smokes.map(t => t.id).join(' ')}\n`);
|
|
@@ -125,7 +125,7 @@ async function begin() {
|
|
|
125
125
|
const rawArgv = y
|
|
126
126
|
.help('help')
|
|
127
127
|
.usage('node $0 [<options>] <test-ids>')
|
|
128
|
-
.example('node $0 -j=1
|
|
128
|
+
.example('node $0 -j=1 perf seo', 'run perf and seo tests serially')
|
|
129
129
|
.option('_', {
|
|
130
130
|
array: true,
|
|
131
131
|
type: 'string',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default RedirectsHTTP;
|
|
2
|
+
/**
|
|
3
|
+
* An audit for checking if a site starting on http redirects to https. The audit
|
|
4
|
+
* is marked not applicable if the requestedUrl is already https.
|
|
5
|
+
*/
|
|
6
|
+
declare class RedirectsHTTP extends Audit {
|
|
7
|
+
/**
|
|
8
|
+
* @param {LH.Artifacts} artifacts
|
|
9
|
+
* @return {LH.Audit.Product}
|
|
10
|
+
*/
|
|
11
|
+
static audit(artifacts: LH.Artifacts): LH.Audit.Product;
|
|
12
|
+
}
|
|
13
|
+
export namespace UIStrings {
|
|
14
|
+
const title: string;
|
|
15
|
+
const failureTitle: string;
|
|
16
|
+
const description: string;
|
|
17
|
+
}
|
|
18
|
+
import { Audit } from './audit.js';
|
|
19
|
+
//# sourceMappingURL=redirects-http.d.ts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2024 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 {Audit} from './audit.js';
|
|
8
|
+
import * as i18n from '../lib/i18n/i18n.js';
|
|
9
|
+
import UrlUtils from '../lib/url-utils.js';
|
|
10
|
+
|
|
11
|
+
const UIStrings = {
|
|
12
|
+
/** Title of a Lighthouse audit that provides detail on HTTP to HTTPS redirects. This descriptive title is shown to users when HTTP traffic is redirected to HTTPS. */
|
|
13
|
+
title: 'Redirects HTTP traffic to HTTPS',
|
|
14
|
+
/** Title of a Lighthouse audit that provides detail on HTTP to HTTPS redirects. This descriptive title is shown to users when HTTP traffic is not redirected to HTTPS. */
|
|
15
|
+
failureTitle: 'Does not redirect HTTP traffic to HTTPS',
|
|
16
|
+
/** Description of a Lighthouse audit that tells the user why they should direct HTTP traffic to HTTPS. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
|
|
17
|
+
description: 'Make sure that you redirect all HTTP ' +
|
|
18
|
+
'traffic to HTTPS in order to enable secure web features for all your users. [Learn more](https://developer.chrome.com/docs/lighthouse/pwa/redirects-http/).',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* An audit for checking if a site starting on http redirects to https. The audit
|
|
25
|
+
* is marked not applicable if the requestedUrl is already https.
|
|
26
|
+
*/
|
|
27
|
+
class RedirectsHTTP extends Audit {
|
|
28
|
+
/**
|
|
29
|
+
* @return {LH.Audit.Meta}
|
|
30
|
+
*/
|
|
31
|
+
static get meta() {
|
|
32
|
+
return {
|
|
33
|
+
id: 'redirects-http',
|
|
34
|
+
title: str_(UIStrings.title),
|
|
35
|
+
failureTitle: str_(UIStrings.failureTitle),
|
|
36
|
+
description: str_(UIStrings.description),
|
|
37
|
+
requiredArtifacts: ['URL'],
|
|
38
|
+
supportedModes: ['navigation'],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {LH.Artifacts} artifacts
|
|
44
|
+
* @return {LH.Audit.Product}
|
|
45
|
+
*/
|
|
46
|
+
static audit(artifacts) {
|
|
47
|
+
if (!artifacts.URL.requestedUrl) {
|
|
48
|
+
throw new Error('Missing requestedUrl');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const requestedUrl = new URL(artifacts.URL.requestedUrl);
|
|
52
|
+
const finalDisplayedUrl = new URL(artifacts.URL.finalDisplayedUrl);
|
|
53
|
+
|
|
54
|
+
// Not applicable unless starting on http.
|
|
55
|
+
const startedInsecure = requestedUrl.protocol === 'http:';
|
|
56
|
+
|
|
57
|
+
// Relax requirements on localhost.
|
|
58
|
+
const isLocalhost = UrlUtils.isLikeLocalhost(finalDisplayedUrl.hostname);
|
|
59
|
+
|
|
60
|
+
if (!startedInsecure || isLocalhost) {
|
|
61
|
+
return {
|
|
62
|
+
score: null,
|
|
63
|
+
notApplicable: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const endedSecure = finalDisplayedUrl.protocol === 'https:';
|
|
68
|
+
return {
|
|
69
|
+
score: Number(endedSecure),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default RedirectsHTTP;
|
|
75
|
+
export {UIStrings};
|
|
@@ -90,15 +90,6 @@ const UIStrings = {
|
|
|
90
90
|
seoCrawlingGroupTitle: 'Crawling and Indexing',
|
|
91
91
|
/** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers. */
|
|
92
92
|
seoCrawlingGroupDescription: 'To appear in search results, crawlers need access to your app.',
|
|
93
|
-
/** Title of the Progressive Web Application (PWA) category of audits. This is displayed at the top of a list of audits focused on topics related to whether or not a site is a progressive web app, e.g. responds offline, uses a service worker, is on https, etc. Also used as a label of a score gauge. */
|
|
94
|
-
pwaCategoryTitle: 'PWA',
|
|
95
|
-
/** Description of the Progressive Web Application (PWA) category. This is displayed at the top of a list of audits focused on topics related to whether or not a site is a progressive web app, e.g. responds offline, uses a service worker, is on https, etc. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
|
|
96
|
-
pwaCategoryDescription: 'These checks validate the aspects of a Progressive Web App. ' +
|
|
97
|
-
'[Learn what makes a good Progressive Web App](https://web.dev/articles/pwa-checklist).',
|
|
98
|
-
/** Description of the Progressive Web Application (PWA) manual checks category, containing a list of additional validators must be run by hand in order to check all PWA best practices. This is displayed at the top of a list of manually run audits focused on topics related to whether or not a site is a progressive web app, e.g. responds offline, uses a service worker, is on https, etc.. No character length limits. */
|
|
99
|
-
pwaCategoryManualDescription: 'These checks are required by the baseline ' +
|
|
100
|
-
'[PWA Checklist](https://web.dev/articles/pwa-checklist) but are ' +
|
|
101
|
-
'not automatically checked by Lighthouse. They do not affect your score but it\'s important that you verify them manually.',
|
|
102
93
|
/** Title of the Best Practices category of audits. This is displayed at the top of a list of audits focused on topics related to following web development best practices and accepted guidelines. Also used as a label of a score gauge; try to limit to 20 characters. */
|
|
103
94
|
bestPracticesCategoryTitle: 'Best Practices',
|
|
104
95
|
/** Title of the Trust & Safety group of audits. This is displayed at the top of a list of audits focused on maintaining user trust and protecting security in web development. */
|
|
@@ -109,10 +100,6 @@ const UIStrings = {
|
|
|
109
100
|
bestPracticesBrowserCompatGroupTitle: 'Browser Compatibility',
|
|
110
101
|
/** Title of the General group of the Best Practices category. Within this section are the audits that don't belong to a specific group but are of general interest. */
|
|
111
102
|
bestPracticesGeneralGroupTitle: 'General',
|
|
112
|
-
/** Title of the Installable section of the web app category. Within this section are audits that check if Chrome supports installing the web site as an app on their device. */
|
|
113
|
-
pwaInstallableGroupTitle: 'Installable',
|
|
114
|
-
/** Title of the "PWA Optimized" section of the web app category. Within this section are audits that check if the developer has taken advantage of features to make their web page more enjoyable and engaging for the user. */
|
|
115
|
-
pwaOptimizedGroupTitle: 'PWA Optimized',
|
|
116
103
|
};
|
|
117
104
|
|
|
118
105
|
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
@@ -137,7 +124,6 @@ const defaultConfig = {
|
|
|
137
124
|
{id: 'Inputs', gatherer: 'inputs'},
|
|
138
125
|
{id: 'IFrameElements', gatherer: 'iframe-elements'},
|
|
139
126
|
{id: 'ImageElements', gatherer: 'image-elements'},
|
|
140
|
-
{id: 'InstallabilityErrors', gatherer: 'installability-errors'},
|
|
141
127
|
{id: 'InspectorIssues', gatherer: 'inspector-issues'},
|
|
142
128
|
{id: 'JsUsage', gatherer: 'js-usage'},
|
|
143
129
|
{id: 'LinkElements', gatherer: 'link-elements'},
|
|
@@ -154,7 +140,6 @@ const defaultConfig = {
|
|
|
154
140
|
{id: 'TagsBlockingFirstPaint', gatherer: 'dobetterweb/tags-blocking-first-paint'},
|
|
155
141
|
{id: 'TraceElements', gatherer: 'trace-elements'},
|
|
156
142
|
{id: 'ViewportDimensions', gatherer: 'viewport-dimensions'},
|
|
157
|
-
{id: 'WebAppManifest', gatherer: 'web-app-manifest'},
|
|
158
143
|
|
|
159
144
|
// Artifact copies are renamed for compatibility with legacy artifacts.
|
|
160
145
|
{id: 'devtoolsLogs', gatherer: 'devtools-log-compat'},
|
|
@@ -168,6 +153,7 @@ const defaultConfig = {
|
|
|
168
153
|
],
|
|
169
154
|
audits: [
|
|
170
155
|
'is-on-https',
|
|
156
|
+
'redirects-http',
|
|
171
157
|
'viewport',
|
|
172
158
|
'metrics/first-contentful-paint',
|
|
173
159
|
'metrics/largest-contentful-paint',
|
|
@@ -185,11 +171,6 @@ const defaultConfig = {
|
|
|
185
171
|
'user-timings',
|
|
186
172
|
'critical-request-chains',
|
|
187
173
|
'redirects',
|
|
188
|
-
'installable-manifest',
|
|
189
|
-
'splash-screen',
|
|
190
|
-
'themed-omnibox',
|
|
191
|
-
'maskable-icon',
|
|
192
|
-
'content-width',
|
|
193
174
|
'image-aspect-ratio',
|
|
194
175
|
'image-size-responsive',
|
|
195
176
|
'deprecations',
|
|
@@ -219,9 +200,6 @@ const defaultConfig = {
|
|
|
219
200
|
'prioritize-lcp-image',
|
|
220
201
|
'csp-xss',
|
|
221
202
|
'script-treemap-data',
|
|
222
|
-
'manual/pwa-cross-browser',
|
|
223
|
-
'manual/pwa-page-transitions',
|
|
224
|
-
'manual/pwa-each-page-has-url',
|
|
225
203
|
'accessibility/accesskeys',
|
|
226
204
|
'accessibility/aria-allowed-attr',
|
|
227
205
|
'accessibility/aria-allowed-role',
|
|
@@ -344,12 +322,6 @@ const defaultConfig = {
|
|
|
344
322
|
title: str_(UIStrings.diagnosticsGroupTitle),
|
|
345
323
|
description: str_(UIStrings.diagnosticsGroupDescription),
|
|
346
324
|
},
|
|
347
|
-
'pwa-installable': {
|
|
348
|
-
title: str_(UIStrings.pwaInstallableGroupTitle),
|
|
349
|
-
},
|
|
350
|
-
'pwa-optimized': {
|
|
351
|
-
title: str_(UIStrings.pwaOptimizedGroupTitle),
|
|
352
|
-
},
|
|
353
325
|
'a11y-best-practices': {
|
|
354
326
|
title: str_(UIStrings.a11yBestPracticesGroupTitle),
|
|
355
327
|
description: str_(UIStrings.a11yBestPracticesGroupDescription),
|
|
@@ -574,6 +546,7 @@ const defaultConfig = {
|
|
|
574
546
|
auditRefs: [
|
|
575
547
|
// Trust & Safety
|
|
576
548
|
{id: 'is-on-https', weight: 5, group: 'best-practices-trust-safety'},
|
|
549
|
+
{id: 'redirects-http', weight: 1, group: 'best-practices-trust-safety'},
|
|
577
550
|
{id: 'geolocation-on-start', weight: 1, group: 'best-practices-trust-safety'},
|
|
578
551
|
{id: 'notification-on-start', weight: 1, group: 'best-practices-trust-safety'},
|
|
579
552
|
{id: 'csp-xss', weight: 0, group: 'best-practices-trust-safety'},
|
|
@@ -581,6 +554,8 @@ const defaultConfig = {
|
|
|
581
554
|
{id: 'paste-preventing-inputs', weight: 3, group: 'best-practices-ux'},
|
|
582
555
|
{id: 'image-aspect-ratio', weight: 1, group: 'best-practices-ux'},
|
|
583
556
|
{id: 'image-size-responsive', weight: 1, group: 'best-practices-ux'},
|
|
557
|
+
{id: 'viewport', weight: 1, group: 'best-practices-ux'},
|
|
558
|
+
{id: 'font-size', weight: 1, group: 'best-practices-ux'},
|
|
584
559
|
// Browser Compatibility
|
|
585
560
|
{id: 'doctype', weight: 1, group: 'best-practices-browser-compat'},
|
|
586
561
|
{id: 'charset', weight: 1, group: 'best-practices-browser-compat'},
|
|
@@ -599,42 +574,25 @@ const defaultConfig = {
|
|
|
599
574
|
manualDescription: str_(UIStrings.seoCategoryManualDescription),
|
|
600
575
|
supportedModes: ['navigation', 'snapshot'],
|
|
601
576
|
auditRefs: [
|
|
602
|
-
|
|
577
|
+
// Should be at least 31% of the score, such that this audit failing
|
|
578
|
+
// results in the SEO category failing.
|
|
579
|
+
// Solve for w:
|
|
580
|
+
// w / (w + T) >= 0.31
|
|
581
|
+
// where T is the sum of all the other weights.
|
|
582
|
+
{id: 'is-crawlable', weight: 93 / 23, group: 'seo-crawl'},
|
|
603
583
|
{id: 'document-title', weight: 1, group: 'seo-content'},
|
|
604
584
|
{id: 'meta-description', weight: 1, group: 'seo-content'},
|
|
605
585
|
{id: 'http-status-code', weight: 1, group: 'seo-crawl'},
|
|
606
586
|
{id: 'link-text', weight: 1, group: 'seo-content'},
|
|
607
587
|
{id: 'crawlable-anchors', weight: 1, group: 'seo-crawl'},
|
|
608
|
-
{id: 'is-crawlable', weight: 1, group: 'seo-crawl'},
|
|
609
588
|
{id: 'robots-txt', weight: 1, group: 'seo-crawl'},
|
|
610
589
|
{id: 'image-alt', weight: 1, group: 'seo-content'},
|
|
611
590
|
{id: 'hreflang', weight: 1, group: 'seo-content'},
|
|
612
591
|
{id: 'canonical', weight: 1, group: 'seo-content'},
|
|
613
|
-
{id: 'font-size', weight: 1, group: 'seo-mobile'},
|
|
614
592
|
// Manual audits
|
|
615
593
|
{id: 'structured-data', weight: 0},
|
|
616
594
|
],
|
|
617
595
|
},
|
|
618
|
-
'pwa': {
|
|
619
|
-
title: str_(UIStrings.pwaCategoryTitle),
|
|
620
|
-
description: str_(UIStrings.pwaCategoryDescription),
|
|
621
|
-
manualDescription: str_(UIStrings.pwaCategoryManualDescription),
|
|
622
|
-
supportedModes: ['navigation'],
|
|
623
|
-
auditRefs: [
|
|
624
|
-
// Installable
|
|
625
|
-
{id: 'installable-manifest', weight: 2, group: 'pwa-installable'},
|
|
626
|
-
// PWA Optimized
|
|
627
|
-
{id: 'splash-screen', weight: 1, group: 'pwa-optimized'},
|
|
628
|
-
{id: 'themed-omnibox', weight: 1, group: 'pwa-optimized'},
|
|
629
|
-
{id: 'content-width', weight: 1, group: 'pwa-optimized'},
|
|
630
|
-
{id: 'viewport', weight: 2, group: 'pwa-optimized'},
|
|
631
|
-
{id: 'maskable-icon', weight: 1, group: 'pwa-optimized'},
|
|
632
|
-
// Manual audits
|
|
633
|
-
{id: 'pwa-cross-browser', weight: 0},
|
|
634
|
-
{id: 'pwa-page-transitions', weight: 0},
|
|
635
|
-
{id: 'pwa-each-page-has-url', weight: 0},
|
|
636
|
-
],
|
|
637
|
-
},
|
|
638
596
|
},
|
|
639
597
|
};
|
|
640
598
|
|
|
@@ -180,7 +180,7 @@ class TargetManager extends ProtocolEventEmitter {
|
|
|
180
180
|
throw err;
|
|
181
181
|
} finally {
|
|
182
182
|
// Resume the target if it was paused, but if it's unnecessary, we don't care about the error.
|
|
183
|
-
await newSession.
|
|
183
|
+
await newSession.sendCommandAndIgnore('Runtime.runIfWaitingForDebugger');
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -498,9 +498,8 @@ async function waitForFullyLoaded(session, networkMonitor, options) {
|
|
|
498
498
|
if (await isPageHung(session)) {
|
|
499
499
|
log.warn('waitFor', 'Page appears to be hung, killing JavaScript...');
|
|
500
500
|
// We don't await these, as we want to exit with PAGE_HUNG
|
|
501
|
-
void session.
|
|
502
|
-
|
|
503
|
-
void session.sendCommand('Runtime.terminateExecution').catch(_ => {});
|
|
501
|
+
void session.sendCommandAndIgnore('Emulation.setScriptExecutionDisabled', {value: true});
|
|
502
|
+
void session.sendCommandAndIgnore('Runtime.terminateExecution');
|
|
504
503
|
throw new LighthouseError(LighthouseError.errors.PAGE_HUNG);
|
|
505
504
|
}
|
|
506
505
|
|
package/core/gather/driver.js
CHANGED
package/core/gather/session.d.ts
CHANGED
|
@@ -40,6 +40,14 @@ export class ProtocolSession extends ProtocolSession_base implements LH.Gatherer
|
|
|
40
40
|
* @return {Promise<LH.CrdpCommands[C]['returnType']>}
|
|
41
41
|
*/
|
|
42
42
|
sendCommand<C extends keyof import("puppeteer-core").ProtocolMapping.Commands>(method: C, ...params: import("puppeteer-core").ProtocolMapping.Commands[C]["paramsType"]): Promise<import("puppeteer-core").ProtocolMapping.Commands[C]["returnType"]>;
|
|
43
|
+
/**
|
|
44
|
+
* Send and if there's an error response, do not reject.
|
|
45
|
+
* @template {keyof LH.CrdpCommands} C
|
|
46
|
+
* @param {C} method
|
|
47
|
+
* @param {LH.CrdpCommands[C]['paramsType']} params
|
|
48
|
+
* @return {Promise<void>}
|
|
49
|
+
*/
|
|
50
|
+
sendCommandAndIgnore<C_1 extends keyof import("puppeteer-core").ProtocolMapping.Commands>(method: C_1, ...params: import("puppeteer-core").ProtocolMapping.Commands[C_1]["paramsType"]): Promise<void>;
|
|
43
51
|
/**
|
|
44
52
|
* Disposes of a session so that it can no longer talk to Chrome.
|
|
45
53
|
* @return {Promise<void>}
|
package/core/gather/session.js
CHANGED
|
@@ -120,6 +120,18 @@ class ProtocolSession extends CrdpEventEmitter {
|
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Send and if there's an error response, do not reject.
|
|
125
|
+
* @template {keyof LH.CrdpCommands} C
|
|
126
|
+
* @param {C} method
|
|
127
|
+
* @param {LH.CrdpCommands[C]['paramsType']} params
|
|
128
|
+
* @return {Promise<void>}
|
|
129
|
+
*/
|
|
130
|
+
sendCommandAndIgnore(method, ...params) {
|
|
131
|
+
return this.sendCommand(method, ...params)
|
|
132
|
+
.catch(e => log.verbose('session', method, e.message)).then(_ => void 0);
|
|
133
|
+
}
|
|
134
|
+
|
|
123
135
|
/**
|
|
124
136
|
* Disposes of a session so that it can no longer talk to Chrome.
|
|
125
137
|
* @return {Promise<void>}
|
|
@@ -7,8 +7,32 @@
|
|
|
7
7
|
import * as Lantern from './types/lantern.js';
|
|
8
8
|
import {NetworkRequestTypes} from './lantern.js';
|
|
9
9
|
import {BaseNode} from './base-node.js';
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
const NON_NETWORK_SCHEMES = [
|
|
12
|
+
'blob', // @see https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
|
|
13
|
+
'data', // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
|
|
14
|
+
'intent', // @see https://developer.chrome.com/docs/multidevice/android/intents/
|
|
15
|
+
'file', // @see https://en.wikipedia.org/wiki/File_URI_scheme
|
|
16
|
+
'filesystem', // @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystem
|
|
17
|
+
'chrome-extension',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Use `NetworkRequest.isNonNetworkRequest(req)` if working with a request.
|
|
22
|
+
* Note: the `protocol` field from CDP can be 'h2', 'http', (not 'https'!) or it'll be url's scheme.
|
|
23
|
+
* https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/protocol/network_handler.cc;l=598-611;drc=56d4a9a9deb30be73adcee8737c73bcb2a5ab64f
|
|
24
|
+
* However, a `new URL(href).protocol` has a colon suffix.
|
|
25
|
+
* https://url.spec.whatwg.org/#dom-url-protocol
|
|
26
|
+
* A URL's `scheme` is specced as the `protocol` sans-colon, but isn't exposed on a URL object.
|
|
27
|
+
* This method can take all 3 of these string types as a parameter.
|
|
28
|
+
* @param {string} protocol Either a networkRequest's `protocol` per CDP or a `new URL(href).protocol`
|
|
29
|
+
* @return {boolean}
|
|
30
|
+
*/
|
|
31
|
+
function isNonNetworkProtocol(protocol) {
|
|
32
|
+
// Strip off any colon
|
|
33
|
+
const urlScheme = protocol.includes(':') ? protocol.slice(0, protocol.indexOf(':')) : protocol;
|
|
34
|
+
return NON_NETWORK_SCHEMES.includes(urlScheme);
|
|
35
|
+
}
|
|
12
36
|
|
|
13
37
|
/**
|
|
14
38
|
* @template [T=any]
|
|
@@ -75,9 +99,9 @@ class NetworkNode extends BaseNode {
|
|
|
75
99
|
*/
|
|
76
100
|
get isNonNetworkProtocol() {
|
|
77
101
|
// The 'protocol' field in devtools a string more like a `scheme`
|
|
78
|
-
return
|
|
102
|
+
return isNonNetworkProtocol(this.request.protocol) ||
|
|
79
103
|
// But `protocol` can fail to be populated if the request fails, so fallback to scheme.
|
|
80
|
-
|
|
104
|
+
isNonNetworkProtocol(this.request.parsedURL.scheme);
|
|
81
105
|
}
|
|
82
106
|
|
|
83
107
|
/**
|
package/core/runner.js
CHANGED
|
@@ -199,32 +199,27 @@ class Runner {
|
|
|
199
199
|
data: sentryContext,
|
|
200
200
|
});
|
|
201
201
|
|
|
202
|
-
/** @type {LH.Artifacts} */
|
|
203
|
-
let artifacts;
|
|
204
202
|
if (settings.auditMode && !settings.gatherMode) {
|
|
205
203
|
// No browser required, just load the artifacts from disk.
|
|
206
204
|
const path = this._getDataSavePath(settings);
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const path = this._getDataSavePath(settings);
|
|
226
|
-
await assetSaver.saveArtifacts(artifacts, path);
|
|
227
|
-
}
|
|
205
|
+
return assetSaver.loadArtifacts(path);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const runnerStatus = {msg: 'Gather phase', id: 'lh:runner:gather'};
|
|
209
|
+
log.time(runnerStatus, 'verbose');
|
|
210
|
+
|
|
211
|
+
const artifacts = await gatherFn({resolvedConfig: options.resolvedConfig});
|
|
212
|
+
log.timeEnd(runnerStatus);
|
|
213
|
+
|
|
214
|
+
// If `gather` is run multiple times before `audit`, the timing entries for each `gather` can pollute one another.
|
|
215
|
+
// We need to clear the timing entries at the end of gathering.
|
|
216
|
+
// Set artifacts.Timing again to ensure lh:runner:gather is included.
|
|
217
|
+
artifacts.Timing = log.takeTimeEntries();
|
|
218
|
+
|
|
219
|
+
// -G means save these to disk (e.g. ./latest-run).
|
|
220
|
+
if (settings.gatherMode) {
|
|
221
|
+
const path = this._getDataSavePath(settings);
|
|
222
|
+
await assetSaver.saveArtifacts(artifacts, path);
|
|
228
223
|
}
|
|
229
224
|
|
|
230
225
|
return artifacts;
|