Skip to content

App Load Time

In order to avoid namespace collisions with performance.mark, the 1fe platform provides app load time utils that can be accessed through platform props. Using these, widget teams to measure how long a process - any process - takes using built-in browser performance marking functionality.

⚠️ Logging does not happen locally. To test logging, promote to integration.

TL;DR:

When a widget is loaded directly by 1fe, 1fe will automatically log your widget’s bundle download duration and set the start time for your widget’s full load time. Widget teams can then mark the end of the widget’s load time with the platform utils, platformProps.utils.appLoadTime.end(). You can also track anything else you want, by calling platformProps.utils.appLoadTime.markStart('event-name') to start tracking, and platformProps.utils.appLoadTime.markEnd('event-name') to log the end of the process, making sure the event names match.

In the widget load time case, the measurement will be logged with the name widgetId, and for the custom event case, the measurement witll be logged with the name widgetId-eventName.

Widgets which load additional child widgets, plugins, chunked bundles, or other dependencies should use appLoadTime to log this process. Applications can log the duration of any additional process they wish, even if they are not loading-related.

Usage

Access the appLoadTime utility through the platform props, and call the functions directly. The utility is exposed as platformProps.utils.appLoadTime.

import { platformProps } from "@1fe/shell";
const WidgetComponent = (props) => {
useEffect(() => {
platformProps.utils.appLoadTime.end(); // mark you widget as ready for interaction
platformProps.utils.appLoadTime.markStart("user-interacts-with-my-widget");
}, []);
};
// somewhere else
import { platformProps } from "@1fe/shell";
const ModalButton = (props) => {
const onClick = () => {
platformProps.utils.appLoadTime.markEnd("user-interacts-with-my-widget"); // example usage, measure time from widget loading to user interaction
};
};

appLoadTime.end

The end() function is called to mark the end of the widget load timer started automatically by the 1fe-shell. It will log the duration of the widget load to the Shell Logger, and should be called when the widget is ready for user interaction.

Call appLoadTime.end() when your Widget is done with it’s largest contentful paint/Time to Interactive and is ready for customers to interact with. This final stage can occur after rendering your initial screen and hydrating it with the data it needs to be called COMPLETE

Type

function end(): void;

appLoadTime.markStart

The markStart function is used to start a timer for a custom event of your choosing. It accepts marker name alongside an optional PerformanceMarkOptions object. Custom events will be prepended with your widgetId so there is no need to include it in the markerName. To log the end of the process, use appLoadTime.markEnd with the same marker name.

Type

function markStart(
markerName: string,
markOptions?: PerformanceMarkOptions = {}
): void;

appLoadTime.markEnd

The markEnd function is used to end a timer for a custom event of your choosing. It accepts marker name alongside an optional PerformanceMarkOptions object. When you have an open mark from appLoadTime.markStart, you can use this function to log the end of the process. The markerName should match the one used in markStart.

Type

function markEnd(
markerName: string,
markOptions?: PerformanceMarkOptions = {}
): PerformanceMeasure | undefined;

appLoadTime.mark

You should use appLoadTIme.markStart / appLoadTime.markEnd instead of this in most cases for tracking custom events.

The mark() function accepts a marker, widget, or item name as a string param, alongside an optional PerformanceMarkOptions object. In this case, the name is always used. Name will be part of the markerName saved to the browser performanceMark object. The options object is saved to the performanceMark object as well, but it is not, by default, logged as part of the end function. In the code, you’ll see this defined as “markStart” instead of “mark” - it is renamed within the 1fe shell before being exposed to widgets.

Type

function mark(
markerName: string,
markOptions: PerformanceMarkOptions = {}
): PerformanceMeasure | undefined;

appLoadTime.getEntries

The getEntries() function should not get much use by consuming widgets - see sections on Additional Usage and Future Improvements for details on when this function will be of use. GetEntries allows the consuming widget to see all performanceMark events logged - including those from other widgets. This could contain any number of items, by any names, with any metadata - always null check, then filter data from this function carefully.

Type

function getEntries(): PerformanceEntryList;

appLoadTime.measure

You should use appLoadTIme.markStart / appLoadTime.markEnd instead of this in most cases for tracking custom events.

The measure() function should not get much use by consuming widgets - see sections on Additional Usage and Future Improvements for details on when this function will be of use. Measure accepts a marker name as a string parameter, and a required [PerformanceMeasureOptions] object. The options object should contain start and end event names.

Type

function measure(
measureName: string,
measureOptions: PerformanceMeasureOptions
): PerformanceMeasure | undefined;

What’s done for your widget, by 1fe, already?

1fe already makes use of this util for download an basic bundle download and instantiation of widgets:

  1. The 1fe WidgetFrame download.ts uses the util to save two startEvents for each widget - one for the “widgetName”, another for widgetName-download.

  2. WidgetFrame download.ts also logs some end events:

    • It will log a download success when it detects that the download has completed successfully.
    • It will log both a download failure, and a widgetName failure if it catches an error.
    • Note: No end event will be logged if the download somehow fails without error - such as the user was left waiting too long, so they closed the window, or their browser froze.
  3. The 1fe shell PluginLoader then uses end() to log an end event when it detects that instantiation has finished.

Direct usage by your widget

A consuming widget could track events other than bundle load by calling mark() and end() independently with a custom name.

For example, they might call mark(“prepare-time-to-interactive”) in their router code when initiating a navigation to the prepare page, and end(“prepare-time-to-interactive”) upon rendering a critical piece of the page.

You should always ensure that your start and end events have exactly the same name, because end events which do not have a matching start event will not be logged. See Gotchas for additional caveats.