Skip to content

Commit 784a924

Browse files
rvetereigneel64
authored andcommitted
Cache browser properties and use the ResizeObserver to update when changed (close snowplow#1295)
PR snowplow#1294
1 parent 70104c4 commit 784a924

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@snowplow/browser-tracker-core",
5+
"comment": "Cache browser properties and use the ResizeObserver to update when changed (#1295) thanks to @rvetere",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@snowplow/browser-tracker-core"
10+
}

libraries/browser-tracker-core/src/helpers/browser_props.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,70 @@
1+
interface BrowserProperties {
2+
viewport?: string | null;
3+
documentSize?: string | null;
4+
resolution?: string | null;
5+
colorDepth: number;
6+
devicePixelRatio: number;
7+
cookiesEnabled: boolean;
8+
online: boolean;
9+
browserLanguage: string;
10+
documentLanguage: string;
11+
webdriver: boolean;
12+
deviceMemory?: number; // Optional because it's not supported in all browsers
13+
hardwareConcurrency?: number;
14+
}
15+
16+
function useResizeObserver(): boolean {
17+
return 'ResizeObserver' in window;
18+
}
19+
20+
let resizeObserverInitialized = false;
21+
function initializeResizeObserver() {
22+
if (resizeObserverInitialized) {
23+
return;
24+
}
25+
resizeObserverInitialized = true;
26+
27+
const resizeObserver = new ResizeObserver((entries) => {
28+
for (let entry of entries) {
29+
if (entry.target === document.body || entry.target === document.documentElement) {
30+
cachedProperties = readBrowserProperties();
31+
}
32+
}
33+
});
34+
resizeObserver.observe(document.body);
35+
resizeObserver.observe(document.documentElement);
36+
}
37+
38+
let cachedProperties: BrowserProperties;
39+
140
/* Separator used for dimension values e.g. widthxheight */
241
const DIMENSION_SEPARATOR = 'x';
342

43+
/**
44+
* Gets various browser properties (that are expensive to read!)
45+
* - Will use a "ResizeObserver" approach in modern browsers to update cached properties only on change
46+
* - Will fallback to a direct read approach without cache in old browsers
47+
*
48+
* @returns BrowserProperties
49+
*/
450
export function getBrowserProperties() {
51+
if (!useResizeObserver()) {
52+
return readBrowserProperties();
53+
}
54+
55+
if (!cachedProperties) {
56+
cachedProperties = readBrowserProperties();
57+
}
58+
initializeResizeObserver();
59+
return cachedProperties;
60+
}
61+
62+
/**
63+
* Reads the browser properties - expensive call!
64+
*
65+
* @returns BrowserProperties
66+
*/
67+
function readBrowserProperties(): BrowserProperties {
568
return {
669
viewport: floorDimensionFields(detectViewport()),
770
documentSize: floorDimensionFields(detectDocumentSize()),

0 commit comments

Comments
 (0)