browsertime 23.3.3 → 23.4.1
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 +15 -0
- package/browserscripts/pageinfo/largestContentfulPaintInfo.js +38 -3
- package/browserscripts/timings/largestContentfulPaint.js +35 -2
- package/browserscripts/timings/userTimings.js +17 -9
- package/lib/chrome/webdriver/chromium.js +18 -0
- package/lib/chrome/webdriver/devtools/domComplete.js +21 -0
- package/lib/chrome/webdriver/devtools/element.js +29 -0
- package/lib/chrome/webdriver/devtools/fcp.js +23 -0
- package/lib/chrome/webdriver/devtools/inp.js +70 -0
- package/lib/chrome/webdriver/devtools/lcp.js +53 -0
- package/lib/chrome/webdriver/devtools/loadEventEnd.js +21 -0
- package/lib/chrome/webdriver/devtools/loaf.js +60 -0
- package/lib/chrome/webdriver/devtools/longtask.js +24 -0
- package/lib/chrome/webdriver/devtools/ttfb.js +21 -0
- package/lib/firefox/settings/firefoxPreferences.js +8 -2
- package/lib/support/cli.js +7 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Browsertime changelog (we do [semantic versioning](https://semver.org))
|
|
2
2
|
|
|
3
|
+
## 23.4.1 - 2024-11-23
|
|
4
|
+
### Fixed
|
|
5
|
+
* Cleanuo of the extra timings that is added to the timeline for Chrome [#2218](https://github.com/sitespeedio/browsertime/pull/2218)
|
|
6
|
+
|
|
7
|
+
## 23.4.0 - 2024-11-22
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
* Collect more information about the largest contentful paint [#2206](https://github.com/sitespeedio/browsertime/pull/2206)
|
|
11
|
+
* Add extra timings and new custom timeline to the Chrome timeline [#2217](https://github.com/sitespeedio/browsertime/pull/2217). Inspired by [
|
|
12
|
+
Andy Davies](https://github.com/andydavies) cool [https://github.com/andydavies/perf-timeline-to-devtools-profile](https://github.com/andydavies/perf-timeline-to-devtools-profile).
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
* More configuration tuning for Firefox [#2216](https://github.com/sitespeedio/browsertime/pull/2216).
|
|
16
|
+
|
|
17
|
+
|
|
3
18
|
## 23.3.3 - 2024-11-22
|
|
4
19
|
### Fixed
|
|
5
20
|
* Disable search suggestion requests for Firefox [#2215](https://github.com/sitespeedio/browsertime/pull/2215)
|
|
@@ -35,24 +35,59 @@
|
|
|
35
35
|
const observer = new PerformanceObserver(list => {});
|
|
36
36
|
observer.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
37
37
|
const entries = observer.takeRecords();
|
|
38
|
+
|
|
39
|
+
const navEntries = performance.getEntriesByType('navigation');
|
|
40
|
+
const navEntry = navEntries.length > 0 ? navEntries[0] : null;
|
|
41
|
+
const ttfb = navEntry ? navEntry.responseStart : 0;
|
|
42
|
+
|
|
38
43
|
const candidates = [];
|
|
39
44
|
for (let entry of entries) {
|
|
40
45
|
const element = entry.element;
|
|
46
|
+
const lcpTime = Math.max(entry.renderTime,entry.loadTime);
|
|
47
|
+
let resourceLoadDelay = 0;
|
|
48
|
+
let resourceLoadDuration = 0;
|
|
49
|
+
let elementRenderDelay = 0;
|
|
50
|
+
|
|
51
|
+
if (navEntry) {
|
|
52
|
+
if (entry.url) {
|
|
53
|
+
const resourceEntries = performance.getEntriesByName(entry.url);
|
|
54
|
+
const resourceEntry = resourceEntries.length > 0 ? resourceEntries[resourceEntries.length - 1] : null;
|
|
55
|
+
if (resourceEntry) {
|
|
56
|
+
resourceLoadDelay = resourceEntry.startTime - ttfb;
|
|
57
|
+
resourceLoadDuration = resourceEntry.responseEnd - resourceEntry.startTime;
|
|
58
|
+
elementRenderDelay = lcpTime - resourceEntry.responseEnd;
|
|
59
|
+
} else {
|
|
60
|
+
// If resource entry not found, set delays appropriately
|
|
61
|
+
resourceLoadDelay = 0;
|
|
62
|
+
resourceLoadDuration = 0;
|
|
63
|
+
elementRenderDelay = lcpTime - ttfb;
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
// For inline resources (text elements or inline images)
|
|
67
|
+
resourceLoadDelay = 0;
|
|
68
|
+
resourceLoadDuration = 0;
|
|
69
|
+
elementRenderDelay = lcpTime - ttfb;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
41
73
|
candidates.push(
|
|
42
74
|
{
|
|
43
75
|
duration: entry.duration,
|
|
44
76
|
id: entry.id,
|
|
45
77
|
url: entry.url,
|
|
46
78
|
loadTime: Number(entry.loadTime.toFixed(0)),
|
|
47
|
-
renderTime: Number(
|
|
79
|
+
renderTime: Number(lcpTime.toFixed(0)),
|
|
48
80
|
size: entry.size,
|
|
49
81
|
startTime: Number(entry.startTime.toFixed(0)),
|
|
50
82
|
tagName: element ? element.tagName : '',
|
|
51
83
|
className: element ? element.className : '',
|
|
52
84
|
domPath: element ? (getDomPath(element)).join( ' > ') : '',
|
|
53
|
-
tag: element ? (element.cloneNode(false)).outerHTML : ''
|
|
85
|
+
tag: element ? (element.cloneNode(false)).outerHTML : '',
|
|
86
|
+
ttfb: Number(ttfb.toFixed(0)),
|
|
87
|
+
resourceLoadDelay: Number(resourceLoadDelay.toFixed(0)),
|
|
88
|
+
resourceLoadDuration: Number(resourceLoadDuration.toFixed(0)),
|
|
89
|
+
elementRenderDelay: Number(elementRenderDelay.toFixed(0))
|
|
54
90
|
}
|
|
55
|
-
|
|
56
91
|
)
|
|
57
92
|
}
|
|
58
93
|
return candidates;
|
|
@@ -34,20 +34,53 @@
|
|
|
34
34
|
const observer = new PerformanceObserver(list => {});
|
|
35
35
|
observer.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
36
36
|
const entries = observer.takeRecords();
|
|
37
|
+
const navEntries = performance.getEntriesByType('navigation');
|
|
38
|
+
const navEntry = navEntries.length > 0 ? navEntries[0] : null;
|
|
39
|
+
const ttfb = navEntry ? navEntry.responseStart : 0;
|
|
37
40
|
if (entries.length > 0) {
|
|
38
41
|
const largestEntry = entries[entries.length - 1];
|
|
42
|
+
const lcpTime = Math.max(largestEntry.renderTime,largestEntry.loadTime);
|
|
43
|
+
let resourceLoadDelay = 0;
|
|
44
|
+
let resourceLoadDuration = 0;
|
|
45
|
+
let elementRenderDelay = 0;
|
|
46
|
+
|
|
47
|
+
if (navEntry) {
|
|
48
|
+
if (largestEntry.url) {
|
|
49
|
+
const resourceEntries = performance.getEntriesByName(largestEntry.url);
|
|
50
|
+
const resourceEntry = resourceEntries.length > 0 ? resourceEntries[resourceEntries.length - 1] : null;
|
|
51
|
+
if (resourceEntry) {
|
|
52
|
+
resourceLoadDelay = resourceEntry.startTime - ttfb;
|
|
53
|
+
resourceLoadDuration = resourceEntry.responseEnd - resourceEntry.startTime;
|
|
54
|
+
elementRenderDelay = lcpTime - resourceEntry.responseEnd;
|
|
55
|
+
} else {
|
|
56
|
+
// If resource entry not found, set delays appropriately
|
|
57
|
+
resourceLoadDelay = 0;
|
|
58
|
+
resourceLoadDuration = 0;
|
|
59
|
+
elementRenderDelay = lcpTime - ttfb;
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
// For inline resources (text elements or inline images)
|
|
63
|
+
resourceLoadDelay = 0;
|
|
64
|
+
resourceLoadDuration = 0;
|
|
65
|
+
elementRenderDelay = lcpTime - ttfb;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
39
68
|
return {
|
|
40
69
|
duration: largestEntry.duration,
|
|
41
70
|
id: largestEntry.id,
|
|
42
71
|
url: largestEntry.url,
|
|
43
72
|
loadTime: Number(largestEntry.loadTime.toFixed(0)),
|
|
44
|
-
renderTime: Number(
|
|
73
|
+
renderTime: Number(lcpTime.toFixed(0)),
|
|
45
74
|
size: largestEntry.size,
|
|
46
75
|
startTime: Number(largestEntry.startTime.toFixed(0)),
|
|
47
76
|
tagName: largestEntry.element ? largestEntry.element.tagName : '',
|
|
48
77
|
className :largestEntry.element ? largestEntry.element.className : '',
|
|
49
78
|
domPath: largestEntry.element ? (getDomPath(largestEntry.element)).join( ' > ') : '',
|
|
50
|
-
tag: largestEntry.element ? (largestEntry.element.cloneNode(false)).outerHTML : ''
|
|
79
|
+
tag: largestEntry.element ? (largestEntry.element.cloneNode(false)).outerHTML : '',
|
|
80
|
+
ttfb: Number(ttfb.toFixed(0)),
|
|
81
|
+
resourceLoadDelay: Number(resourceLoadDelay.toFixed(0)),
|
|
82
|
+
resourceLoadDuration: Number(resourceLoadDuration.toFixed(0)),
|
|
83
|
+
elementRenderDelay: Number(elementRenderDelay.toFixed(0))
|
|
51
84
|
};
|
|
52
85
|
} else return;
|
|
53
86
|
})();
|
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
);
|
|
9
9
|
|
|
10
10
|
for (const mark of myMarks) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
if (mark.detail && mark.detail.devtools) {
|
|
12
|
+
continue;
|
|
13
|
+
} else {
|
|
14
|
+
marks.push({
|
|
15
|
+
name: mark.name,
|
|
16
|
+
startTime: mark.startTime
|
|
17
|
+
});
|
|
18
|
+
}
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
const myMeasures = Array.prototype.slice.call(
|
|
@@ -19,11 +23,15 @@
|
|
|
19
23
|
);
|
|
20
24
|
|
|
21
25
|
for (const measure of myMeasures) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
if (measure.detail && measure.detail.devtools) {
|
|
27
|
+
continue;
|
|
28
|
+
} else {
|
|
29
|
+
measures.push({
|
|
30
|
+
name: measure.name,
|
|
31
|
+
duration: measure.duration,
|
|
32
|
+
startTime: measure.startTime
|
|
33
|
+
});
|
|
34
|
+
}
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
|
|
@@ -18,6 +18,14 @@ import { ChromeDevtoolsProtocol } from '../chromeDevtoolsProtocol.js';
|
|
|
18
18
|
import { NetworkManager } from '../networkManager.js';
|
|
19
19
|
import { Android, isAndroidConfigured } from '../../android/index.js';
|
|
20
20
|
import { getRenderBlocking } from './traceUtilities.js';
|
|
21
|
+
import { loafTimeLine } from './devtools/loaf.js';
|
|
22
|
+
import { lcpTimeLine } from './devtools/lcp.js';
|
|
23
|
+
import { fcpTimeLine } from './devtools/fcp.js';
|
|
24
|
+
import { ttfbTimeLine } from './devtools/ttfb.js';
|
|
25
|
+
import { elementTimeLine } from './devtools/element.js';
|
|
26
|
+
import { longtaskTimeLine } from './devtools/longtask.js';
|
|
27
|
+
import { domCompleteTimeLine } from './devtools/domComplete.js';
|
|
28
|
+
import { loadEventEndTimeLine } from './devtools/loadEventEnd.js';
|
|
21
29
|
const unlink = promisify(_unlink);
|
|
22
30
|
const rm = promisify(_rm);
|
|
23
31
|
|
|
@@ -192,6 +200,16 @@ export class Chromium {
|
|
|
192
200
|
this.isTracing &&
|
|
193
201
|
this.options.chrome.timelineRecordingType !== 'custom'
|
|
194
202
|
) {
|
|
203
|
+
if (this.options.chrome.timelineExtras != false) {
|
|
204
|
+
await runner.runScript(ttfbTimeLine, 'TTFB_SCRIPT');
|
|
205
|
+
await runner.runScript(loafTimeLine, 'LOAF_SCRIPT');
|
|
206
|
+
await runner.runScript(fcpTimeLine, 'FCP_SCRIPT');
|
|
207
|
+
await runner.runScript(lcpTimeLine, 'LCP_SCRIPT');
|
|
208
|
+
await runner.runScript(elementTimeLine, 'ELEMENT_SCRIPT');
|
|
209
|
+
await runner.runScript(longtaskTimeLine, 'LONGTASK_SCRIPT');
|
|
210
|
+
await runner.runScript(domCompleteTimeLine, 'DOMCOMPLETE_SCRIPT');
|
|
211
|
+
await runner.runScript(loadEventEndTimeLine, 'LOADEVENTEND_SCRIPT');
|
|
212
|
+
}
|
|
195
213
|
// We are ready and can stop collecting events
|
|
196
214
|
this.isTracing = false;
|
|
197
215
|
this.events = await this.cdpClient.stopTrace();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const domCompleteTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
performance.mark('DOM Complete', {
|
|
6
|
+
startTime: window.performance.getEntriesByType('navigation')[0].domComplete,
|
|
7
|
+
detail: {
|
|
8
|
+
devtools: {
|
|
9
|
+
dataType: 'marker',
|
|
10
|
+
trackGroup: 'Browsertime Timeline',
|
|
11
|
+
track: 'Metrics',
|
|
12
|
+
color: 'tertiary-dark',
|
|
13
|
+
tooltipText: 'DOM Complete',
|
|
14
|
+
properties: [
|
|
15
|
+
['DOMComplete', window.performance.getEntriesByType('navigation')[0].domComplete]
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
})();
|
|
21
|
+
`;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const elementTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
const observer = new PerformanceObserver(list => { });
|
|
6
|
+
observer.observe({ type: 'element', buffered: true });
|
|
7
|
+
const entries = observer.takeRecords();
|
|
8
|
+
for (let entry of entries) {
|
|
9
|
+
performance.mark(entry.identifier, {
|
|
10
|
+
startTime: entry.renderTime,
|
|
11
|
+
detail: {
|
|
12
|
+
devtools: {
|
|
13
|
+
dataType: 'marker',
|
|
14
|
+
track: 'Metrics',
|
|
15
|
+
trackGroup: 'Browsertime Timeline',
|
|
16
|
+
color: 'primary',
|
|
17
|
+
tooltipText: entry.identifier + ' element',
|
|
18
|
+
properties: [
|
|
19
|
+
['tagName', '' + entry.element ? entry.element.tagName:''],
|
|
20
|
+
['className', '' + entry.element ? entry.element.className:''],
|
|
21
|
+
['URL', '' + entry.url]
|
|
22
|
+
['Render', entry.renderTime]
|
|
23
|
+
],
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
})();
|
|
29
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const fcpTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
const observer = new PerformanceObserver(list => { });
|
|
6
|
+
observer.observe({ type: 'paint', buffered: true });
|
|
7
|
+
const entries = observer.takeRecords();
|
|
8
|
+
for (let entry of entries) {
|
|
9
|
+
performance.mark(entry.name === 'first-contentful-paint' ? 'FCP': 'FP', {
|
|
10
|
+
startTime: entry.startTime,
|
|
11
|
+
detail: {
|
|
12
|
+
devtools: {
|
|
13
|
+
dataType: 'marker',
|
|
14
|
+
track: 'Metrics',
|
|
15
|
+
trackGroup: 'Browsertime Timeline',
|
|
16
|
+
color: 'primary',
|
|
17
|
+
tooltipText: entry.name
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
`;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Adopted from https://github.com/andydavies/perf-timeline-to-devtools-profile
|
|
2
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
3
|
+
|
|
4
|
+
export const inpTimeLine = `
|
|
5
|
+
(function() {
|
|
6
|
+
const observer = new PerformanceObserver(list => {});
|
|
7
|
+
for (const type of ['event']) {
|
|
8
|
+
observer.observe({ type, buffered: true, durationThreshold: 0});
|
|
9
|
+
}
|
|
10
|
+
let inpEventCount = 0;
|
|
11
|
+
const entries = observer.takeRecords();
|
|
12
|
+
for (const entry of entries) {
|
|
13
|
+
if(entry.entryType == 'event' && entry.interactionId > 0) {
|
|
14
|
+
inpEventCount++;
|
|
15
|
+
performance.measure('Input Delay', {
|
|
16
|
+
start: entry.startTime,
|
|
17
|
+
end: entry.processingStart,
|
|
18
|
+
detail: {
|
|
19
|
+
devtools: {
|
|
20
|
+
dataType: 'track-entry',
|
|
21
|
+
track: 'INP.' + inpEventCount,
|
|
22
|
+
trackGroup: 'Browsertime Timeline',
|
|
23
|
+
color: 'primary',
|
|
24
|
+
tooltipText: 'Input Delay',
|
|
25
|
+
properties: [
|
|
26
|
+
['name', '' + entry.name],
|
|
27
|
+
['target', '' + entry.target.tagName]
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
performance.measure('Processing Time', {
|
|
33
|
+
start: entry.processingStart,
|
|
34
|
+
end: entry.processingEnd,
|
|
35
|
+
detail: {
|
|
36
|
+
devtools: {
|
|
37
|
+
|
|
38
|
+
dataType: 'track-entry',
|
|
39
|
+
track: 'INP.' + inpEventCount,
|
|
40
|
+
trackGroup: 'Browsertime Timeline',
|
|
41
|
+
color: 'primary',
|
|
42
|
+
tooltipText: 'Processing Time',
|
|
43
|
+
properties: [
|
|
44
|
+
['name', '' + entry.name],
|
|
45
|
+
['target', '' + entry.target.tagName]
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
performance.measure('Presentation Delay', {
|
|
51
|
+
start: entry.processingEnd,
|
|
52
|
+
end: entry.startTime + entry.duration,
|
|
53
|
+
detail: {
|
|
54
|
+
devtools: {
|
|
55
|
+
dataType: 'track-entry',
|
|
56
|
+
track: 'INP.' + inpEventCount,
|
|
57
|
+
trackGroup: 'Browsertime Timeline',
|
|
58
|
+
color: 'primary',
|
|
59
|
+
tooltipText: 'Presentation Delay',
|
|
60
|
+
properties: [
|
|
61
|
+
['name', '' + entry.name],
|
|
62
|
+
['target', '' + entry.target.tagName]
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
})();
|
|
70
|
+
`;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const lcpTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
const observer = new PerformanceObserver(list => { });
|
|
6
|
+
observer.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
7
|
+
const entries = observer.takeRecords();
|
|
8
|
+
entries.forEach((entry, index) => {
|
|
9
|
+
if (index === entries.length - 1) {
|
|
10
|
+
// This is the LCP
|
|
11
|
+
performance.mark('LCP', {
|
|
12
|
+
startTime: Math.max(entry.renderTime, entry.loadTime),
|
|
13
|
+
detail: {
|
|
14
|
+
devtools: {
|
|
15
|
+
dataType: 'marker',
|
|
16
|
+
track: 'Metrics',
|
|
17
|
+
trackGroup: 'Browsertime Timeline',
|
|
18
|
+
color: 'primary-dark',
|
|
19
|
+
tooltipText: 'LCP ' + (entry.element?.tagName || ''),
|
|
20
|
+
properties: [
|
|
21
|
+
['size', '' + entry.size],
|
|
22
|
+
['tagName', '' + (entry.element?.tagName || '')],
|
|
23
|
+
['className', '' + (entry.element?.className || '')],
|
|
24
|
+
['URL', '' + entry.url],
|
|
25
|
+
['Render', Math.max(entry.renderTime, entry.loadTime)]
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
// LCP candidates
|
|
32
|
+
performance.mark('LCP candidate', {
|
|
33
|
+
startTime: Math.max(entry.renderTime, entry.loadTime),
|
|
34
|
+
detail: {
|
|
35
|
+
devtools: {
|
|
36
|
+
dataType: 'marker',
|
|
37
|
+
track: 'LCP',
|
|
38
|
+
trackGroup: 'Browsertime Timeline',
|
|
39
|
+
color: 'primary-dark',
|
|
40
|
+
tooltipText: 'LCP Candidate ' + (entry.element?.tagName || ''),
|
|
41
|
+
properties: [
|
|
42
|
+
['size', '' + entry.size],
|
|
43
|
+
['tagName', '' + (entry.element?.tagName || '')],
|
|
44
|
+
['className', '' + (entry.element?.className || '')],
|
|
45
|
+
['URL', '' + entry.url]
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
})();
|
|
53
|
+
`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const loadEventEndTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
performance.mark('Load Event End', {
|
|
6
|
+
startTime: performance.getEntriesByType('navigation')[0].loadEventEnd,
|
|
7
|
+
detail: {
|
|
8
|
+
devtools: {
|
|
9
|
+
dataType: 'marker',
|
|
10
|
+
trackGroup: 'Browsertime Timeline',
|
|
11
|
+
track: 'Metrics',
|
|
12
|
+
color: 'secondary',
|
|
13
|
+
tooltipText: 'Load Event End',
|
|
14
|
+
properties: [
|
|
15
|
+
['LoadEventEnd', window.performance.getEntriesByType('navigation')[0].loadEventEnd]
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
})();
|
|
21
|
+
`;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Adopted from https://github.com/andydavies/perf-timeline-to-devtools-profile
|
|
2
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
3
|
+
|
|
4
|
+
export const loafTimeLine = `
|
|
5
|
+
(function () {
|
|
6
|
+
const observer = new PerformanceObserver(list => { });
|
|
7
|
+
observer.observe({ type: 'long-animation-frame', buffered: true, durationThreshold: 0 });
|
|
8
|
+
const entries = observer.takeRecords();
|
|
9
|
+
for (let entry of entries) {
|
|
10
|
+
|
|
11
|
+
// Set script entries before LoAF so Chrome can display them in the right order
|
|
12
|
+
for(const script of entry.scripts) {
|
|
13
|
+
performance.measure('script', {
|
|
14
|
+
start: script.startTime,
|
|
15
|
+
end: script.startTime + script.duration,
|
|
16
|
+
detail: {
|
|
17
|
+
devtools: {
|
|
18
|
+
dataType: 'track-entry',
|
|
19
|
+
track: 'LoAF',
|
|
20
|
+
trackGroup: 'Browsertime Timeline',
|
|
21
|
+
color: 'secondary',
|
|
22
|
+
tooltipText: script.sourceURL
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
performance.measure('LoAF', {
|
|
29
|
+
start: entry.startTime,
|
|
30
|
+
end: entry.startTime + entry.duration,
|
|
31
|
+
detail: {
|
|
32
|
+
devtools: {
|
|
33
|
+
dataType: 'track-entry',
|
|
34
|
+
track: 'LoAF',
|
|
35
|
+
trackGroup: 'Browsertime Timeline',
|
|
36
|
+
color: 'primary',
|
|
37
|
+
tooltipText: 'LoAF'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if(entry.styleAndLayoutStart > 0) {
|
|
43
|
+
performance.measure('Layout + Paint', {
|
|
44
|
+
start: entry.styleAndLayoutStart,
|
|
45
|
+
end: entry.startTime + entry.duration,
|
|
46
|
+
detail: {
|
|
47
|
+
devtools: {
|
|
48
|
+
|
|
49
|
+
dataType: 'track-entry',
|
|
50
|
+
track: 'LoAF',
|
|
51
|
+
trackGroup: 'Browsertime Timeline',
|
|
52
|
+
color: 'secondary-light',
|
|
53
|
+
tooltipText: 'Layout + Paint'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
})();
|
|
60
|
+
`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const longtaskTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
const observer = new PerformanceObserver(list => { });
|
|
6
|
+
observer.observe({ type: 'longtask', buffered: true, durationThreshold: 0 });
|
|
7
|
+
const entries = observer.takeRecords();
|
|
8
|
+
for (let entry of entries) {
|
|
9
|
+
performance.measure('Long Task', {
|
|
10
|
+
start: entry.startTime,
|
|
11
|
+
end: entry.startTime + entry.duration,
|
|
12
|
+
detail: {
|
|
13
|
+
devtools: {
|
|
14
|
+
dataType: 'track-entry',
|
|
15
|
+
track: 'Long Task',
|
|
16
|
+
trackGroup: 'Browsertime Timeline',
|
|
17
|
+
color: 'error',
|
|
18
|
+
tooltipText: 'Long Task'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
})();
|
|
24
|
+
`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// https://developer.chrome.com/docs/devtools/performance/extension
|
|
2
|
+
|
|
3
|
+
export const ttfbTimeLine = `
|
|
4
|
+
(function () {
|
|
5
|
+
performance.mark('TTFB', {
|
|
6
|
+
startTime: window.performance.getEntriesByType('navigation')[0].responseStart,
|
|
7
|
+
detail: {
|
|
8
|
+
devtools: {
|
|
9
|
+
dataType: 'marker',
|
|
10
|
+
trackGroup: 'Browsertime Timeline',
|
|
11
|
+
track: 'Metrics',
|
|
12
|
+
color: 'tertiary-light',
|
|
13
|
+
tooltipText: 'Time To First Byte (TTFB)',
|
|
14
|
+
properties: [
|
|
15
|
+
['TTFB', window.performance.getEntriesByType('navigation')[0].responseStart]
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
})();
|
|
21
|
+
`;
|
|
@@ -57,7 +57,7 @@ export const defaultFirefoxPreferences = {
|
|
|
57
57
|
'security.turn_off_all_security_so_that_viruses_can_take_over_this_computer': true,
|
|
58
58
|
'xpinstall.signatures.required': false,
|
|
59
59
|
// Prevent Remote Settings to issue non local connections.
|
|
60
|
-
'services.settings.server': '
|
|
60
|
+
'services.settings.server': 'data:,#remote-settings-dummy/v1',
|
|
61
61
|
// Ensure autoplay is enabled for all platforms.
|
|
62
62
|
'media.autoplay.default': 0, // 0=Allowed, 1=Blocked, 2=Prompt
|
|
63
63
|
'media.autoplay.enabled.user-gestures-needed': true,
|
|
@@ -198,5 +198,11 @@ export const defaultFirefoxPreferences = {
|
|
|
198
198
|
'browser.newtabpage.activity-stream.showSponsoredTopSites': false,
|
|
199
199
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1930110
|
|
200
200
|
// See https://github.com/sitespeedio/browsertime/issues/2211
|
|
201
|
-
'browser.search.serpEventTelemetryCategorization.enabled': false
|
|
201
|
+
'browser.search.serpEventTelemetryCategorization.enabled': false,
|
|
202
|
+
// Default Glean to "record but don't report" mode, and to never trigger
|
|
203
|
+
// activity-based ping submission. Docs:
|
|
204
|
+
// https://firefox-source-docs.mozilla.org/toolkit/components/glean/dev/preferences.html
|
|
205
|
+
'telemetry.fog.test.localhost_port': -1,
|
|
206
|
+
'telemetry.fog.test.activity_limit': -1,
|
|
207
|
+
'telemetry.fog.test.inactivity_limit': -1
|
|
202
208
|
};
|
package/lib/support/cli.js
CHANGED
|
@@ -288,6 +288,13 @@ export function parseCommandLine() {
|
|
|
288
288
|
type: 'boolean',
|
|
289
289
|
group: 'chrome'
|
|
290
290
|
})
|
|
291
|
+
.option('chrome.timelineExtras', {
|
|
292
|
+
describe:
|
|
293
|
+
'If you collect the timeline using --chrome.timeline or --enableProfileRun this will add some extra timings and tracks to your timeline.',
|
|
294
|
+
type: 'boolean',
|
|
295
|
+
default: true,
|
|
296
|
+
group: 'chrome'
|
|
297
|
+
})
|
|
291
298
|
.option('chrome.timelineRecordingType', {
|
|
292
299
|
alias: 'chrome.traceRecordingType',
|
|
293
300
|
describe: 'Expose the start/stop commands for the chrome trace',
|
package/package.json
CHANGED