Skip to content

Commit cea2c0b

Browse files
author
Reno
authored
fix: Use PerformanceObserver to act as a second check to prevent returning 0 for duration and loadEventEnd (#101)
1 parent 94efb04 commit cea2c0b

File tree

3 files changed

+26
-10
lines changed

3 files changed

+26
-10
lines changed

src/plugins/event-plugins/NavigationPlugin.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ export class NavigationPlugin implements Plugin {
2323
}
2424

2525
/**
26-
* If the client is initialized after the window has fired a load event,
27-
* invoke the callback method directly to trigger the record event.
28-
* Otherwise, keep the original implementation to add callback method to eventListener.
29-
* However, if the page finishes loading right before adding addEventListener, we still cannot provide data
26+
* loadEventEnd is populated as 0 if the web page has not loaded completely, even though LOAD has been fired.
27+
* As a result, if loadEventEnd is populated, we can ignore eventListener and record the data directly.
28+
* On the other hand, if not, we have to use eventListener to initializes PerformanceObserver.
29+
* PerformanceObserver will act as a second check for the final load timings.
3030
*/
3131
load(context: PluginContext): void {
3232
this.recordEvent = context.record;
3333
if (this.enabled) {
3434
if (this.hasTheWindowLoadEventFired()) {
35-
this.eventListener();
35+
const navData = window.performance.getEntriesByType(
36+
NAVIGATION
37+
)[0] as PerformanceNavigationTiming;
38+
this.performanceNavigationEventHandlerTimingLevel2(navData);
3639
} else {
3740
window.addEventListener(LOAD, this.eventListener);
3841
}
@@ -94,9 +97,18 @@ export class NavigationPlugin implements Plugin {
9497
if (performance.getEntriesByType(NAVIGATION).length === 0) {
9598
this.performanceNavigationEventHandlerTimingLevel1();
9699
} else {
97-
this.performanceNavigationEventHandlerTimingLevel2(
98-
performance.getEntriesByType(NAVIGATION)[0]
99-
);
100+
const navigationObserver = new PerformanceObserver((list) => {
101+
list.getEntries().forEach((event) => {
102+
if (event.entryType === NAVIGATION) {
103+
this.performanceNavigationEventHandlerTimingLevel2(
104+
event
105+
);
106+
}
107+
});
108+
});
109+
navigationObserver.observe({
110+
entryTypes: [NAVIGATION]
111+
});
100112
}
101113
};
102114

src/plugins/event-plugins/__integ__/NavigationPlugin.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ test('when plugin loads after window.load then navigation timing events are reco
122122
.contains(DURATION)
123123

124124
.expect(RESPONSE_STATUS.textContent)
125-
.eql(STATUS_202.toString());
125+
.eql(STATUS_202.toString())
126+
.expect((await REQUEST_BODY.textContent).indexOf(DURATION))
127+
.gt(0);
126128

127129
/**
128130
* Deprecated Timing Level1 used for Safari browser do not contain following attributes

src/plugins/event-plugins/__integ__/PerformancePlugin.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ test('PerformanceEvent records navigation event', async (t: TestController) => {
131131
.contains(DURATION)
132132

133133
.expect(RESPONSE_STATUS.textContent)
134-
.eql(STATUS_202.toString());
134+
.eql(STATUS_202.toString())
135+
.expect((await REQUEST_BODY.textContent).indexOf(DURATION))
136+
.gt(0);
135137

136138
/**
137139
* Deprecated Timing Level1 used for Safari browser do not contain following attributes

0 commit comments

Comments
 (0)