Skip to content

Commit 3486aea

Browse files
authored
Merge pull request #1733 from rosahbruno/1845362-ssr-support
2 parents dbc3a2c + d2f801c commit 3486aea

File tree

6 files changed

+42
-2
lines changed

6 files changed

+42
-2
lines changed

.dictionary

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,4 @@ webpack
7878
async
7979
queueing
8080
LocalStorage
81+
ssr

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
[Full changelog](https://github.com/mozilla/glean.js/compare/v1.4.0...main)
44

5+
* [#1733](https://github.com/mozilla/glean.js/pull/1733): Add SSR support for Glean.js
56
* [#1728](https://github.com/mozilla/glean.js/pull/1728): Migrate client_id and first_run_date.
67
* [#1695](https://github.com/mozilla/glean.js/pull/1695): Update Glean.js web to use LocalStorage.
78

glean/src/core/internal_metrics/sync.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { InternalDatetimeMetricType as DatetimeMetricType } from "../metrics/typ
1111
import { InternalStringMetricType as StringMetricType } from "../metrics/types/string.js";
1212
import { createMetric } from "../metrics/utils.js";
1313
import TimeUnit from "../metrics/time_unit.js";
14-
import { generateUUIDv4 } from "../utils.js";
14+
import { generateUUIDv4, isWindowObjectUnavailable } from "../utils.js";
1515
import { Lifetime } from "../metrics/lifetime.js";
1616
import log, { LoggingLevel } from "../log.js";
1717
import { Context } from "../context.js";
@@ -126,6 +126,13 @@ export class CoreMetricsSync {
126126
}
127127

128128
initialize(): void {
129+
// The "sync" version of Glean.js is only meant to be used in the browser.
130+
// If we cannot access the window object, then we are unable to store
131+
// any of the metric data in `localStorage`.
132+
if (isWindowObjectUnavailable()) {
133+
return;
134+
}
135+
129136
// If the client had used previous versions of Glean.js before we moved
130137
// to LocalStorage as the data store, then we need to move important
131138
// user data from IndexedDB to LocalStorage.

glean/src/core/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,15 @@ export function getCurrentTimeInNanoSeconds(): number {
311311
}
312312
return now;
313313
}
314+
315+
/**
316+
* Checks if the current environment has access to the `window` object. This
317+
* check is used to conditional-ize browser code for SSR projects. If the
318+
* platform does not have access to the `window` APIs, then we are unable to
319+
* store data in the browser.
320+
*
321+
* @returns Whether or not the current platform has access to the `window` object.
322+
*/
323+
export function isWindowObjectUnavailable(): boolean {
324+
return typeof window === "undefined";
325+
}

glean/src/platform/browser/web/platform_info.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import { KnownOperatingSystems } from "../../../core/platform_info/shared.js";
77

88
const BrowserPlatformInfo: PlatformInfoSync = {
99
os(): KnownOperatingSystems {
10-
const ua = navigator.userAgent;
10+
let ua;
11+
if (!!navigator && !!navigator.userAgent) {
12+
ua = navigator.userAgent;
13+
} else {
14+
ua = KnownOperatingSystems.Unknown;
15+
}
1116

1217
if (ua.includes("Windows")) {
1318
return KnownOperatingSystems.Windows;

glean/src/platform/browser/web/storage.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import {
1212
getValueFromNestedObject,
1313
updateNestedObject
1414
} from "../../../core/storage/utils.js";
15+
import { isWindowObjectUnavailable } from "../../../core/utils.js";
1516

1617
const LOG_TAG = "platform.web.Storage";
1718

19+
// If `window.localStorage` is unavailable, we return undefined for all.
1820
class WebStore implements SynchronousStore {
1921
private logTag: string;
2022

@@ -23,6 +25,10 @@ class WebStore implements SynchronousStore {
2325
}
2426

2527
get(index: StorageIndex = []): JSONValue | undefined {
28+
if (isWindowObjectUnavailable()) {
29+
return;
30+
}
31+
2632
let result;
2733

2834
try {
@@ -42,6 +48,10 @@ class WebStore implements SynchronousStore {
4248
}
4349

4450
update(index: StorageIndex, transformFn: (v?: JSONValue) => JSONValue): void {
51+
if (isWindowObjectUnavailable()) {
52+
return;
53+
}
54+
4555
try {
4656
const json = localStorage.getItem(this.rootKey) || "{}";
4757
const obj = JSON.parse(json) as JSONObject;
@@ -54,6 +64,10 @@ class WebStore implements SynchronousStore {
5464
}
5565

5666
delete(index: StorageIndex): void {
67+
if (isWindowObjectUnavailable()) {
68+
return;
69+
}
70+
5771
try {
5872
const json = localStorage.getItem(this.rootKey) || "{}";
5973
const obj = JSON.parse(json) as JSONObject;

0 commit comments

Comments
 (0)