lighthouse 12.3.0-dev.20250223 → 12.3.0-dev.20250224
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/core/audits/layout-shifts.d.ts +0 -1
- package/core/audits/layout-shifts.js +17 -20
- package/core/config/default-config.js +0 -1
- package/core/gather/gatherers/trace-elements.d.ts +2 -2
- package/core/gather/gatherers/trace-elements.js +27 -20
- package/package.json +1 -1
- package/shared/localization/locales/ar-XB.json +0 -3
- package/shared/localization/locales/ar.json +0 -3
- package/shared/localization/locales/bg.json +0 -3
- package/shared/localization/locales/ca.json +0 -3
- package/shared/localization/locales/cs.json +0 -3
- package/shared/localization/locales/da.json +0 -3
- package/shared/localization/locales/de.json +0 -3
- package/shared/localization/locales/el.json +0 -3
- package/shared/localization/locales/en-GB.json +0 -3
- package/shared/localization/locales/en-US.json +0 -3
- package/shared/localization/locales/en-XA.json +0 -3
- package/shared/localization/locales/en-XL.json +0 -3
- package/shared/localization/locales/es-419.json +0 -3
- package/shared/localization/locales/es.json +0 -3
- package/shared/localization/locales/fi.json +0 -3
- package/shared/localization/locales/fil.json +0 -3
- package/shared/localization/locales/fr.json +0 -3
- package/shared/localization/locales/he.json +0 -3
- package/shared/localization/locales/hi.json +0 -3
- package/shared/localization/locales/hr.json +0 -3
- package/shared/localization/locales/hu.json +0 -3
- package/shared/localization/locales/id.json +0 -3
- package/shared/localization/locales/it.json +0 -3
- package/shared/localization/locales/ja.json +0 -3
- package/shared/localization/locales/ko.json +0 -3
- package/shared/localization/locales/lt.json +0 -3
- package/shared/localization/locales/lv.json +0 -3
- package/shared/localization/locales/nl.json +0 -3
- package/shared/localization/locales/no.json +0 -3
- package/shared/localization/locales/pl.json +0 -3
- package/shared/localization/locales/pt-PT.json +0 -3
- package/shared/localization/locales/pt.json +0 -3
- package/shared/localization/locales/ro.json +0 -3
- package/shared/localization/locales/ru.json +0 -3
- package/shared/localization/locales/sk.json +0 -3
- package/shared/localization/locales/sl.json +0 -3
- package/shared/localization/locales/sr-Latn.json +0 -3
- package/shared/localization/locales/sr.json +0 -3
- package/shared/localization/locales/sv.json +0 -3
- package/shared/localization/locales/ta.json +0 -3
- package/shared/localization/locales/te.json +0 -3
- package/shared/localization/locales/th.json +0 -3
- package/shared/localization/locales/tr.json +0 -3
- package/shared/localization/locales/uk.json +0 -3
- package/shared/localization/locales/vi.json +0 -3
- package/shared/localization/locales/zh-HK.json +0 -3
- package/shared/localization/locales/zh-TW.json +0 -3
- package/shared/localization/locales/zh.json +0 -3
- package/types/artifacts.d.ts +1 -2
- package/core/gather/gatherers/root-causes.d.ts +0 -19
- package/core/gather/gatherers/root-causes.js +0 -144
|
@@ -26,7 +26,6 @@ export namespace UIStrings {
|
|
|
26
26
|
let rootCauseUnsizedMedia: string;
|
|
27
27
|
let rootCauseFontChanges: string;
|
|
28
28
|
let rootCauseInjectedIframe: string;
|
|
29
|
-
let rootCauseRenderBlockingRequest: string;
|
|
30
29
|
let displayValueShiftsFound: string;
|
|
31
30
|
}
|
|
32
31
|
import { Audit } from './audit.js';
|
|
@@ -29,8 +29,6 @@ const UIStrings = {
|
|
|
29
29
|
rootCauseFontChanges: 'Web font loaded',
|
|
30
30
|
/** A possible reason why that the layout shift occured. */
|
|
31
31
|
rootCauseInjectedIframe: 'Injected iframe',
|
|
32
|
-
/** A possible reason why that the layout shift occured. */
|
|
33
|
-
rootCauseRenderBlockingRequest: 'A late network request adjusted the page layout',
|
|
34
32
|
/** Label shown per-audit to show how many layout shifts are present. The `{# shifts found}` placeholder will be replaced with the number of layout shifts. */
|
|
35
33
|
displayValueShiftsFound: `{shiftCount, plural, =1 {1 layout shift found} other {# layout shifts found}}`,
|
|
36
34
|
};
|
|
@@ -49,7 +47,7 @@ class LayoutShifts extends Audit {
|
|
|
49
47
|
description: str_(UIStrings.description),
|
|
50
48
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
51
49
|
guidanceLevel: 2,
|
|
52
|
-
requiredArtifacts: ['traces', '
|
|
50
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
53
51
|
};
|
|
54
52
|
}
|
|
55
53
|
|
|
@@ -67,6 +65,16 @@ class LayoutShifts extends Audit {
|
|
|
67
65
|
const traceElements = artifacts.TraceElements
|
|
68
66
|
.filter(element => element.traceEventType === 'layout-shift');
|
|
69
67
|
|
|
68
|
+
/** @type {LH.Artifacts.TraceEngineRootCauses} */
|
|
69
|
+
const allRootCauses = {
|
|
70
|
+
layoutShifts: new Map(),
|
|
71
|
+
};
|
|
72
|
+
for (const insightSet of traceEngineResult.insights.values()) {
|
|
73
|
+
for (const [shift, reasons] of insightSet.model.CLSCulprits.shifts) {
|
|
74
|
+
allRootCauses.layoutShifts.set(shift, reasons);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
/** @type {Item[]} */
|
|
71
79
|
const items = [];
|
|
72
80
|
const layoutShiftEvents =
|
|
@@ -82,41 +90,30 @@ class LayoutShifts extends Audit {
|
|
|
82
90
|
const biggestImpactElement = traceElements.find(t => t.nodeId === biggestImpactNodeId);
|
|
83
91
|
|
|
84
92
|
// Turn root causes into sub-items.
|
|
85
|
-
const
|
|
86
|
-
const rootCauses = artifacts.RootCauses.layoutShifts[index];
|
|
93
|
+
const rootCauses = allRootCauses.layoutShifts.get(event);
|
|
87
94
|
/** @type {SubItem[]} */
|
|
88
95
|
const subItems = [];
|
|
89
96
|
if (rootCauses) {
|
|
90
|
-
for (const
|
|
97
|
+
for (const backendNodeId of rootCauses.unsizedImages) {
|
|
91
98
|
const element = artifacts.TraceElements.find(
|
|
92
|
-
t => t.traceEventType === '
|
|
99
|
+
t => t.traceEventType === 'trace-engine' && t.nodeId === backendNodeId);
|
|
93
100
|
subItems.push({
|
|
94
101
|
extra: element ? Audit.makeNodeItem(element.node) : undefined,
|
|
95
102
|
cause: str_(UIStrings.rootCauseUnsizedMedia),
|
|
96
103
|
});
|
|
97
104
|
}
|
|
98
|
-
for (const
|
|
99
|
-
const url =
|
|
105
|
+
for (const request of rootCauses.fontRequests) {
|
|
106
|
+
const url = request.args.data.url;
|
|
100
107
|
subItems.push({
|
|
101
108
|
extra: {type: 'url', value: url},
|
|
102
109
|
cause: str_(UIStrings.rootCauseFontChanges),
|
|
103
110
|
});
|
|
104
111
|
}
|
|
105
|
-
|
|
106
|
-
const element = artifacts.TraceElements.find(
|
|
107
|
-
t => t.traceEventType === 'layout-shift' && t.nodeId === cause.iframe.backendNodeId);
|
|
112
|
+
if (rootCauses.iframeIds.length) {
|
|
108
113
|
subItems.push({
|
|
109
|
-
extra: element ? Audit.makeNodeItem(element.node) : undefined,
|
|
110
114
|
cause: str_(UIStrings.rootCauseInjectedIframe),
|
|
111
115
|
});
|
|
112
116
|
}
|
|
113
|
-
for (const cause of rootCauses.renderBlockingRequests) {
|
|
114
|
-
const url = cause.request.args.data.url;
|
|
115
|
-
subItems.push({
|
|
116
|
-
extra: {type: 'url', value: url},
|
|
117
|
-
cause: str_(UIStrings.rootCauseRenderBlockingRequest),
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
items.push({
|
|
@@ -109,7 +109,6 @@ const defaultConfig = {
|
|
|
109
109
|
// Artifacts which can be depended on come first.
|
|
110
110
|
{id: 'DevtoolsLog', gatherer: 'devtools-log'},
|
|
111
111
|
{id: 'Trace', gatherer: 'trace'},
|
|
112
|
-
{id: 'RootCauses', gatherer: 'root-causes'},
|
|
113
112
|
|
|
114
113
|
{id: 'Accessibility', gatherer: 'accessibility'},
|
|
115
114
|
{id: 'AnchorElements', gatherer: 'anchor-elements'},
|
|
@@ -56,8 +56,8 @@ declare class TraceElements extends BaseGatherer {
|
|
|
56
56
|
nodeId: number;
|
|
57
57
|
type: string;
|
|
58
58
|
} | undefined>;
|
|
59
|
-
/** @type {LH.Gatherer.GathererMeta<'Trace'
|
|
60
|
-
meta: LH.Gatherer.GathererMeta<"Trace"
|
|
59
|
+
/** @type {LH.Gatherer.GathererMeta<'Trace'>} */
|
|
60
|
+
meta: LH.Gatherer.GathererMeta<"Trace">;
|
|
61
61
|
/** @type {Map<string, string>} */
|
|
62
62
|
animationIdToName: Map<string, string>;
|
|
63
63
|
/** @param {LH.Crdp.Animation.AnimationStartedEvent} args */
|
|
@@ -23,7 +23,6 @@ import {LighthouseError} from '../../lib/lh-error.js';
|
|
|
23
23
|
import {Responsiveness} from '../../computed/metrics/responsiveness.js';
|
|
24
24
|
import {CumulativeLayoutShift} from '../../computed/metrics/cumulative-layout-shift.js';
|
|
25
25
|
import {ExecutionContext} from '../driver/execution-context.js';
|
|
26
|
-
import RootCauses from './root-causes.js';
|
|
27
26
|
import {TraceEngineResult} from '../../computed/trace-engine-result.js';
|
|
28
27
|
|
|
29
28
|
/** @typedef {{nodeId: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[], type?: string}} TraceElementData */
|
|
@@ -46,10 +45,10 @@ function getNodeDetailsData() {
|
|
|
46
45
|
/* c8 ignore stop */
|
|
47
46
|
|
|
48
47
|
class TraceElements extends BaseGatherer {
|
|
49
|
-
/** @type {LH.Gatherer.GathererMeta<'Trace'
|
|
48
|
+
/** @type {LH.Gatherer.GathererMeta<'Trace'>} */
|
|
50
49
|
meta = {
|
|
51
50
|
supportedModes: ['timespan', 'navigation'],
|
|
52
|
-
dependencies: {Trace: Trace.symbol
|
|
51
|
+
dependencies: {Trace: Trace.symbol},
|
|
53
52
|
};
|
|
54
53
|
|
|
55
54
|
/** @type {Map<string, string>} */
|
|
@@ -103,13 +102,23 @@ class TraceElements extends BaseGatherer {
|
|
|
103
102
|
seen.add(obj);
|
|
104
103
|
|
|
105
104
|
if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
if (obj instanceof Map) {
|
|
106
|
+
for (const [key, val] of obj) {
|
|
107
|
+
if (typeof val === 'object') {
|
|
108
|
+
recursiveObjectEnumerate(val, cb, seen);
|
|
109
|
+
} else {
|
|
110
|
+
cb(val, key);
|
|
111
|
+
}
|
|
111
112
|
}
|
|
112
|
-
}
|
|
113
|
+
} else {
|
|
114
|
+
Object.keys(obj).forEach(key => {
|
|
115
|
+
if (typeof obj[key] === 'object') {
|
|
116
|
+
recursiveObjectEnumerate(obj[key], cb, seen);
|
|
117
|
+
} else {
|
|
118
|
+
cb(obj[key], key);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
113
122
|
} else if (Array.isArray(obj)) {
|
|
114
123
|
obj.forEach(item => {
|
|
115
124
|
if (typeof item === 'object' || Array.isArray(item)) {
|
|
@@ -121,12 +130,18 @@ class TraceElements extends BaseGatherer {
|
|
|
121
130
|
|
|
122
131
|
/** @type {number[]} */
|
|
123
132
|
const nodeIds = [];
|
|
124
|
-
recursiveObjectEnumerate(insightSet.model, (
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
recursiveObjectEnumerate(insightSet.model, (val, key) => {
|
|
134
|
+
const keys = ['nodeId', 'node_id'];
|
|
135
|
+
if (typeof val === 'number' && keys.includes(key)) {
|
|
136
|
+
nodeIds.push(val);
|
|
127
137
|
}
|
|
128
138
|
}, new Set());
|
|
129
139
|
|
|
140
|
+
// TODO: would be better if unsizedImages was `Array<{nodeId}>`.
|
|
141
|
+
for (const shift of insightSet.model.CLSCulprits.shifts.values()) {
|
|
142
|
+
nodeIds.push(...shift.unsizedImages);
|
|
143
|
+
}
|
|
144
|
+
|
|
130
145
|
return [...new Set(nodeIds)].map(id => ({nodeId: id}));
|
|
131
146
|
}
|
|
132
147
|
|
|
@@ -212,14 +227,6 @@ class TraceElements extends BaseGatherer {
|
|
|
212
227
|
nodeIds.push(biggestImpactedNodeId);
|
|
213
228
|
}
|
|
214
229
|
|
|
215
|
-
const index = layoutShiftEvents.indexOf(event);
|
|
216
|
-
const shiftRootCauses = rootCauses.layoutShifts[index];
|
|
217
|
-
if (shiftRootCauses) {
|
|
218
|
-
for (const cause of shiftRootCauses.unsizedMedia) {
|
|
219
|
-
nodeIds.push(cause.node.backendNodeId);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
230
|
return nodeIds.map(nodeId => ({nodeId}));
|
|
224
231
|
});
|
|
225
232
|
}
|
package/package.json
CHANGED
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Injected iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "A late network request adjusted the page layout"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Media element lacking an explicit size"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "إطار iframe الذي تم إدخاله"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "أدَّى طلب الشبكة المتأخّر إلى تعديل تصميم الصفحة."
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "لم يتم تحديد حجم واضح لعنصر الوسائط."
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Вмъкната вложена рамка"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Оформлението на страницата е коригирано заради закъсняла заявка в мрежата"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Липсва конкретен размер за мултимедийния елемент"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "S'ha injectat un iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Una sol·licitud de xarxa amb retard ha ajustat el disseny de la pàgina"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "L'element multimèdia no té una mida explícita"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Byl vložen prvek iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Rozvržení stránky bylo upraveno pozdním síťovým požadavkem"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "U prvku média není explicitně zadána velikost"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Iframe er indsat"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "En sen netværksanmodning har justeret sidens layout"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Medieelementet mangler en klar angivelse af størrelse"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Eingefügter iFrame"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Das Seitenlayout wurde durch eine späte Netzwerkanfrage angepasst"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Medienelement ohne explizite Größe"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Έγινε εισαγωγή iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Ένα αίτημα δικτύου που έχει καθυστερήσει προσάρμοσε τη διάταξη της σελίδας"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Λείπει σαφές μέγεθος από το στοιχείο μέσων"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Injected iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "A late network request adjusted the page layout"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Media element lacking an explicit size"
|
|
1090
1087
|
},
|
|
@@ -1127,9 +1127,6 @@
|
|
|
1127
1127
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1128
1128
|
"message": "Injected iframe"
|
|
1129
1129
|
},
|
|
1130
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1131
|
-
"message": "A late network request adjusted the page layout"
|
|
1132
|
-
},
|
|
1133
1130
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1134
1131
|
"message": "Media element lacking an explicit size"
|
|
1135
1132
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "[Îñĵéçţéð îƒŕåmé one two]"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "[Å ļåţé ñéţŵöŕķ ŕéqûéšţ åðĵûšţéð ţĥé þåĝé ļåýöûţ one two three four five six seven eight nine ten]"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "[Méðîå éļéméñţ ļåçķîñĝ åñ éxþļîçîţ šîžé one two three four five six seven eight]"
|
|
1090
1087
|
},
|
|
@@ -1127,9 +1127,6 @@
|
|
|
1127
1127
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1128
1128
|
"message": "Îńĵéĉt́êd́ îf́r̂ám̂é"
|
|
1129
1129
|
},
|
|
1130
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1131
|
-
"message": "Â ĺât́ê ńêt́ŵór̂ḱ r̂éq̂úêśt̂ ád̂j́ûśt̂éd̂ t́ĥé p̂áĝé l̂áŷóût́"
|
|
1132
|
-
},
|
|
1133
1130
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1134
1131
|
"message": "M̂éd̂íâ él̂ém̂én̂t́ l̂áĉḱîńĝ án̂ éx̂ṕl̂íĉít̂ śîźê"
|
|
1135
1132
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iframe insertado"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Una solicitud de red tardía ajustó el diseño de la página"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Elemento multimedia sin tamaño explícito"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Iframe inyectado"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Una solicitud de red tardía ha cambiado el diseño de la página"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Elemento multimedia sin tamaño concreto"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Lisätty iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Myöhästynyt verkkopyyntö muutti sivun asettelua"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Mediaelementiltä puuttuu tarkka koko"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Na-inject na iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "In-adjust ng nahuling request sa network ang layout ng page"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Walang explicit na laki ang element ng media"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iFrame injecté"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Une requête réseau tardive a ajusté la mise en page"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Élément multimédia sans taille explicite"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "החדרת iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "בקשת רשת מאוחרת גרמה לשינוי בפריסת הדף"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "רכיב מדיה שהגודל שלו לא מוגדר"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "इंजेक्ट किया गया iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "नेटवर्क के देर से अनुरोध करने की वजह से, पेज के लेआउट में बदलाव हुआ है"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "मीडिया एलिमेंट के साइज़ की जानकारी साफ़ तौर पर नहीं दी गई है"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Ugrađeni iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Izgled stranice promijenjen je zbog kasnog mrežnog zahtjeva"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Medijski element bez eksplicitne veličine"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Iframe került beszúrásra"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Egy későn beérkező hálózati kérelem módosította az oldal elrendezését"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Hiányzik egy médiaelem pontos mérete"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Memasukkan iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Permintaan jaringan yang terlambat menyesuaikan tata letak halaman"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Elemen media tidak memiliki ukuran yang jelas"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "È stato inserito un iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Una richiesta di rete in ritardo ha modificato il layout della pagina"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "L'elemento multimediale è privo di dimensioni esplicite"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "挿入された iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "遅延したネットワーク リクエストによりページ レイアウトが調整されました"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "メディア要素に明示的なサイズが含まれていません"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "삽입된 iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "네트워크 요청이 늦어져 페이지 레이아웃이 조정됨"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "명시적인 크기가 없는 미디어 요소"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Įterptas „iframe“"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Pavėluota tinklo užklausa pakoregavo puslapio išdėstymą"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Trūksta aiškaus medijos elemento dydžio"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Tika iepludināts iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Tika pielāgots lapas izkārtojums novēlota tīkla pieprasījuma dēļ"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Multivides elementam nav skaidra lieluma"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Geïnjecteerd iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Door een laat netwerkverzoek is de pagina-indeling aangepast"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Media-element heeft geen expliciet formaat"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Injisert iframe-element"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "En sen nettverksforespørsel justerte sideutseendet"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Medieelement uten eksplisitt størrelse"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Wstrzyknięty element iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Spóźnione żądanie sieciowe spowodowało zmianę układu strony"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Element multimedialny nie ma wyraźnego rozmiaru"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iFrame injetado"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Um pedido de rede atrasado ajustou o esquema da página"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Elemento de multimédia sem um tamanho explícito"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iframe injetado"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Uma solicitação tardia de rede ajustou o layout da página"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Elemento de mídia sem tamanho explícito"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "S-a injectat un iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "O solicitare din rețea întârziată a ajustat aspectul paginii"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Elementul media nu are o dimensiune clară"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Внедрение окна iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Изменение макета страницы при последнем сетевом запросе"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "У медиаэлемента нет заданного явным образом размера"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Vložený prvok iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Posledná sieťová požiadavka upravila rozloženie stránky"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Mediálny prvok nemá explicitnú veľkosť"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Vstavljen okvir iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Pozna omrežna zahteva je prilagodila postavitev strani"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Predstavnostni element nima eksplicitne velikosti"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Umetnuti iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Kasni mrežni zahtev je prilagodio raspored stranice"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Medijski element nema eksplicitnu veličinu"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Уметнути iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Касни мрежни захтев је прилагодио распоред странице"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Медијски елемент нема експлицитну величину"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Injicerad iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "En sen nätverksbegäran justerade sidlayouten"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Medieelementet har ingen angiven storlek"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iframe சேர்க்கப்பட்டிருத்தல்"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "தாமதமான நெட்வொர்க் கோரிக்கை காரணமாகப் பக்கத்தின் தளவமைப்பு மாறியிருக்கலாம்"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "மீடியா உறுப்பின் அளவு வரையறுக்கப்படாமல் இருத்தல்"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iframe ఇంజెక్ట్ చేయబడింది"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "లేట్ నెట్వర్క్ రిక్వెస్ట్ కారణంగా పేజీ లేఅవుట్ మార్చబడింది"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "మీడియా ఎలిమెంట్ సైజ్ తగినది కాదు"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "มีการแทรก iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "คำขอเครือข่ายที่ส่งล่าช้าได้ปรับเลย์เอาต์ของหน้า"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "องค์ประกอบสื่อมีขนาดที่ไม่เหมาะสม"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Yerleştirilen iFrame"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Geç gelen bir ağ isteği, sayfa düzenini değiştirdi"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Açık bir boyutu olmayan medya öğesi"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "Вставлено iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Макет сторінки змінено через запізній запит мережі"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Для медіаоб’єкта не вказано явний розмір"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "iframe được chèn"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "Yêu cầu kết nối mạng chậm trễ đã điều chỉnh bố cục trang"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "Phần tử nội dung đa phương tiện không có kích thước rõ ràng"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "已插入 iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "延遲的網絡要求導致網頁版面配置變更"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "媒體元素沒有明確尺寸"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "插入了 iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "延遲的網路要求導致網頁版面配置變更"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "媒體元素沒有明確尺寸"
|
|
1090
1087
|
},
|
|
@@ -1082,9 +1082,6 @@
|
|
|
1082
1082
|
"core/audits/layout-shifts.js | rootCauseInjectedIframe": {
|
|
1083
1083
|
"message": "注入的 iframe"
|
|
1084
1084
|
},
|
|
1085
|
-
"core/audits/layout-shifts.js | rootCauseRenderBlockingRequest": {
|
|
1086
|
-
"message": "延迟的网络请求调整了页面布局"
|
|
1087
|
-
},
|
|
1088
1085
|
"core/audits/layout-shifts.js | rootCauseUnsizedMedia": {
|
|
1089
1086
|
"message": "媒体元素缺少明确的大小"
|
|
1090
1087
|
},
|
package/types/artifacts.d.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import {Protocol as Crdp} from 'devtools-protocol/types/protocol.js';
|
|
8
8
|
import * as TraceEngine from '@paulirish/trace_engine';
|
|
9
9
|
import * as Lantern from '../core/lib/lantern/lantern.js';
|
|
10
|
-
import {LayoutShiftRootCausesData} from '@paulirish/trace_engine/models/trace/root-causes/LayoutShift.js';
|
|
11
10
|
|
|
12
11
|
import {parseManifest} from '../core/lib/manifest-parser.js';
|
|
13
12
|
import {LighthouseError} from '../core/lib/lh-error.js';
|
|
@@ -515,7 +514,7 @@ declare module Artifacts {
|
|
|
515
514
|
}
|
|
516
515
|
|
|
517
516
|
interface TraceEngineRootCauses {
|
|
518
|
-
layoutShifts:
|
|
517
|
+
layoutShifts: Map<TraceEngine.Types.Events.SyntheticLayoutShift, TraceEngine.Insights.Models.CLSCulprits.LayoutShiftRootCausesData>;
|
|
519
518
|
}
|
|
520
519
|
|
|
521
520
|
interface ViewportDimensions {
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export default RootCauses;
|
|
2
|
-
declare class RootCauses extends BaseGatherer {
|
|
3
|
-
static symbol: symbol;
|
|
4
|
-
/**
|
|
5
|
-
* @param {LH.Gatherer.Driver} driver
|
|
6
|
-
* @param {LH.Artifacts.TraceEngineResult['data']} traceParsedData
|
|
7
|
-
* @return {Promise<LH.Artifacts.TraceEngineRootCauses>}
|
|
8
|
-
*/
|
|
9
|
-
static runRootCauseAnalysis(driver: LH.Gatherer.Driver, traceParsedData: LH.Artifacts.TraceEngineResult["data"]): Promise<LH.Artifacts.TraceEngineRootCauses>;
|
|
10
|
-
/** @type {LH.Gatherer.GathererMeta<'Trace'>} */
|
|
11
|
-
meta: LH.Gatherer.GathererMeta<"Trace">;
|
|
12
|
-
/**
|
|
13
|
-
* @param {LH.Gatherer.Context<'Trace'>} context
|
|
14
|
-
* @return {Promise<LH.Artifacts.TraceEngineRootCauses>}
|
|
15
|
-
*/
|
|
16
|
-
getArtifact(context: LH.Gatherer.Context<"Trace">): Promise<LH.Artifacts.TraceEngineRootCauses>;
|
|
17
|
-
}
|
|
18
|
-
import BaseGatherer from '../base-gatherer.js';
|
|
19
|
-
//# sourceMappingURL=root-causes.d.ts.map
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2023 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import BaseGatherer from '../base-gatherer.js';
|
|
8
|
-
import Trace from './trace.js';
|
|
9
|
-
import * as TraceEngine from '../../lib/trace-engine.js';
|
|
10
|
-
import {TraceEngineResult} from '../../computed/trace-engine-result.js';
|
|
11
|
-
|
|
12
|
-
class RootCauses extends BaseGatherer {
|
|
13
|
-
static symbol = Symbol('RootCauses');
|
|
14
|
-
|
|
15
|
-
/** @type {LH.Gatherer.GathererMeta<'Trace'>} */
|
|
16
|
-
meta = {
|
|
17
|
-
symbol: RootCauses.symbol,
|
|
18
|
-
supportedModes: ['timespan', 'navigation'],
|
|
19
|
-
dependencies: {Trace: Trace.symbol},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param {LH.Gatherer.Driver} driver
|
|
24
|
-
* @param {LH.Artifacts.TraceEngineResult['data']} traceParsedData
|
|
25
|
-
* @return {Promise<LH.Artifacts.TraceEngineRootCauses>}
|
|
26
|
-
*/
|
|
27
|
-
static async runRootCauseAnalysis(driver, traceParsedData) {
|
|
28
|
-
await driver.defaultSession.sendCommand('DOM.enable');
|
|
29
|
-
await driver.defaultSession.sendCommand('CSS.enable');
|
|
30
|
-
|
|
31
|
-
// DOM.getDocument is necessary for pushNodesByBackendIdsToFrontend to properly retrieve
|
|
32
|
-
// nodeIds if the DOM domain was enabled before this gatherer, invoke it to be safe.
|
|
33
|
-
await driver.defaultSession.sendCommand('DOM.getDocument', {depth: -1, pierce: true});
|
|
34
|
-
|
|
35
|
-
/** @type {import('@paulirish/trace_engine').RootCauses.RootCauses.RootCauseProtocolInterface} */
|
|
36
|
-
const protocolInterface = {
|
|
37
|
-
/** @param {string} url */
|
|
38
|
-
// eslint-disable-next-line no-unused-vars
|
|
39
|
-
getInitiatorForRequest(url) {
|
|
40
|
-
return null;
|
|
41
|
-
},
|
|
42
|
-
/** @param {import('@paulirish/trace_engine/generated/protocol.js').DOM.BackendNodeId[]} backendNodeIds */
|
|
43
|
-
async pushNodesByBackendIdsToFrontend(backendNodeIds) {
|
|
44
|
-
const response = await driver.defaultSession.sendCommand(
|
|
45
|
-
'DOM.pushNodesByBackendIdsToFrontend', {backendNodeIds});
|
|
46
|
-
const nodeIds =
|
|
47
|
-
/** @type {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId[]} */(
|
|
48
|
-
response.nodeIds);
|
|
49
|
-
return nodeIds;
|
|
50
|
-
},
|
|
51
|
-
/** @param {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId} nodeId */
|
|
52
|
-
async getNode(nodeId) {
|
|
53
|
-
try {
|
|
54
|
-
const response = await driver.defaultSession.sendCommand('DOM.describeNode', {nodeId});
|
|
55
|
-
// This always zero, so let's fix it here.
|
|
56
|
-
// https://bugs.chromium.org/p/chromium/issues/detail?id=1515175
|
|
57
|
-
response.node.nodeId = nodeId;
|
|
58
|
-
const node =
|
|
59
|
-
/** @type {import('@paulirish/trace_engine/generated/protocol.js').DOM.Node} */(
|
|
60
|
-
response.node);
|
|
61
|
-
return node;
|
|
62
|
-
} catch (err) {
|
|
63
|
-
if (err.message.includes('Could not find node with given id')) {
|
|
64
|
-
// TODO: when injecting an iframe, the engine gets the node of that frame's document element.
|
|
65
|
-
// But we don't have a way to access that frame. We just have our default session.
|
|
66
|
-
// Ex:
|
|
67
|
-
// node cli http://localhost:10503/shift-attribution.html --quiet --only-audits layout-shifts
|
|
68
|
-
// To fix we must:
|
|
69
|
-
// - Change trace engine `getNode` protocol interface to also give frame id
|
|
70
|
-
// - Expand our driver.targetManager to know how to talk to a session connected to a specific frame
|
|
71
|
-
// When this is fixed, remove this try/catch.
|
|
72
|
-
// Note: this could be buggy by giving the wrong node detail if a node id meant for a non-main frame
|
|
73
|
-
// happens to match one from the main frame ... which is pretty likely...
|
|
74
|
-
// TODO: fix trace engine type to allow returning null.
|
|
75
|
-
return /** @type {any} */(null);
|
|
76
|
-
}
|
|
77
|
-
throw err;
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
/** @param {number} nodeId */
|
|
81
|
-
async getComputedStyleForNode(nodeId) {
|
|
82
|
-
try {
|
|
83
|
-
const response = await driver.defaultSession.sendCommand(
|
|
84
|
-
'CSS.getComputedStyleForNode', {nodeId});
|
|
85
|
-
return response.computedStyle;
|
|
86
|
-
} catch {
|
|
87
|
-
return [];
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
/** @param {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId} nodeId */
|
|
91
|
-
async getMatchedStylesForNode(nodeId) {
|
|
92
|
-
try {
|
|
93
|
-
const response = await driver.defaultSession.sendCommand(
|
|
94
|
-
'CSS.getMatchedStylesForNode', {nodeId});
|
|
95
|
-
return {...response, getError() {}};
|
|
96
|
-
} catch (err) {
|
|
97
|
-
return /** @type {any} */({getError() {
|
|
98
|
-
return err.toString();
|
|
99
|
-
}});
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
/** @param {string} url */
|
|
103
|
-
// @ts-expect-error not using, dont care about type error.
|
|
104
|
-
// eslint-disable-next-line no-unused-vars
|
|
105
|
-
async fontFaceForSource(url) {
|
|
106
|
-
return null;
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/** @type {LH.Artifacts.TraceEngineRootCauses} */
|
|
111
|
-
const rootCauses = {
|
|
112
|
-
layoutShifts: {},
|
|
113
|
-
};
|
|
114
|
-
const rootCausesEngine = new TraceEngine.RootCauses(protocolInterface);
|
|
115
|
-
const layoutShiftEvents = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);
|
|
116
|
-
for (const event of layoutShiftEvents) {
|
|
117
|
-
const r = await rootCausesEngine.layoutShifts.rootCausesForEvent(traceParsedData, event);
|
|
118
|
-
if (!r) continue;
|
|
119
|
-
|
|
120
|
-
for (const cause of r.fontChanges) {
|
|
121
|
-
// TODO: why isn't trace engine unwrapping this promise ...
|
|
122
|
-
cause.fontFace = await cause.fontFace;
|
|
123
|
-
}
|
|
124
|
-
rootCauses.layoutShifts[layoutShiftEvents.indexOf(event)] = r;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
await driver.defaultSession.sendCommand('DOM.disable');
|
|
128
|
-
await driver.defaultSession.sendCommand('CSS.disable');
|
|
129
|
-
|
|
130
|
-
return rootCauses;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @param {LH.Gatherer.Context<'Trace'>} context
|
|
135
|
-
* @return {Promise<LH.Artifacts.TraceEngineRootCauses>}
|
|
136
|
-
*/
|
|
137
|
-
async getArtifact(context) {
|
|
138
|
-
const trace = context.dependencies.Trace;
|
|
139
|
-
const traceEngineResult = await TraceEngineResult.request({trace}, context);
|
|
140
|
-
return RootCauses.runRootCauseAnalysis(context.driver, traceEngineResult.data);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export default RootCauses;
|