Skip to content

GAUD-10126: switch from unload to pagehide#41

Merged
dlockhart merged 1 commit into
mainfrom
GAUD-10126/remove-unload
Jun 12, 2026
Merged

GAUD-10126: switch from unload to pagehide#41
dlockhart merged 1 commit into
mainfrom
GAUD-10126/remove-unload

Conversation

@dlockhart

Copy link
Copy Markdown
Member

This switches our logger to use the pagehide event in the wake of Google dropping support for unload.

Testing this was pretty tricky since Chrome has a tendency to run the code but not any console.logs or show anything in the network traffic. I did confirm though that errors ended up getting logged on back/forward, reload and link clicking in Firefox, Chrome, Edge and Safari.

@dlockhart dlockhart requested a review from a team as a code owner June 11, 2026 19:40
Comment thread package.json
"access": "public"
},
"main": "index.js",
"type": "module",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This project was already ESM, so I don't think this is going to be a problem.

Comment thread package.json
"author": "D2L Corporation",
"license": "Apache-2.0",
"devDependencies": {
"@babel/core": "^7",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was doing weird things in the lint output.

Comment thread logging.js
async _onPageHide() {
clearTimeout(this._batchTimeout);
if (!this._loggerPromise && !navigator || !navigator.sendBeacon) {
if (!this._loggerPromise || !navigator?.sendBeacon || this._logs.length === 0) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think this was a bug before -- it should have been !this._loggerPromise || !navigator || !navigator.sendBeach. I added the empty _logs check to reduce the nesting of the code below.

Comment thread logging.js

_disconnectForTesting() {
window.removeEventListener('pagehide', this._onPageHide);
clearTimeout(this._batchTimeout);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tests I added were failing sporadically because the old loggers from the other tests were still doing things after their tests finished!

Comment thread test/logging.test.js
await aTimeout(0);

expect(beaconStub).to.have.been.calledOnce;
expect(beaconStub.calledOnce).to.be.true;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other format of this expect was blowing up when testing the failure scenario.

Comment thread logging.js
this._logs = [];
window.addEventListener('unload', this._onUnload.bind(this));
this._onPageHide = this._onPageHide.bind(this);
window.addEventListener('pagehide', this._onPageHide);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I specifically didn't feature flag this since our logger both runs in so many places that likely don't have access to our feature flags but also runs so early in the page cycle.

Comment thread logging.js
this._logs = [];
window.addEventListener('unload', this._onUnload.bind(this));
this._onPageHide = this._onPageHide.bind(this);
window.addEventListener('pagehide', this._onPageHide);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should mention that I spent a lot of time looking into visibilitychange as well, as it's also recommended in the same breath as pagehide for sendBeacon. It was pretty unreliable in Chrome, but also fires every time the user switches tabs, which we don't really care about here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation says:

The pagehide event is sent to a Window when the browser hides the current page in the process of presenting a different page from the session's history.
For example, when the user clicks the browser's Back button, the current page receives a pagehide event before the previous page is shown.

I'm guessing pageHide event fires when navigating to a new page not in the user's session history, but this description doesn't make it sound that way.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does yes. Following a link (both on the same domain or another), reloading the current page, as well as normal back/forward all trigger it.

@dlockhart dlockhart merged commit b42728c into main Jun 12, 2026
2 checks passed
@dlockhart dlockhart deleted the GAUD-10126/remove-unload branch June 12, 2026 16:38
@d2l-github-release-tokens

Copy link
Copy Markdown

🎉 This PR is included in version 1.9.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants