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 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(Math.max(entry.renderTime,entry.loadTime).toFixed(0)),
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(Math.max(largestEntry.renderTime,largestEntry.loadTime).toFixed(0)),
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
- marks.push({
12
- name: mark.name,
13
- startTime: mark.startTime
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
- measures.push({
23
- name: measure.name,
24
- duration: measure.duration,
25
- startTime: measure.startTime
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': 'http://localhost/remote-settings-dummy/v1',
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
  };
@@ -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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "browsertime",
3
3
  "description": "Get performance metrics from your web page using Browsertime.",
4
- "version": "23.3.3",
4
+ "version": "23.4.1",
5
5
  "bin": "./bin/browsertime.js",
6
6
  "type": "module",
7
7
  "types": "./types/scripting.d.ts",