Skip to content

Commit 6f0e926

Browse files
committed
perf(insights): better minify/compress
1 parent e030275 commit 6f0e926

File tree

4 files changed

+58
-67
lines changed

4 files changed

+58
-67
lines changed

packages/qwik/src/insights/insights.ts

Lines changed: 36 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -82,123 +82,93 @@ interface QSymbolDetail {
8282

8383
// We use a self-invoking function to minify the code, renaming long globals and attributes
8484
// the qwik optimizer only minifies somewhat, so put all var declarations in the same line
85-
const insightsPing = sync$(() =>
86-
((
87-
window: QwikSymbolTrackerWindow,
88-
document,
89-
location,
90-
navigator,
91-
performance,
92-
round,
93-
JSON_stringify
94-
) => {
85+
/** @internal */
86+
export const insightsPing = sync$(() =>
87+
((w: QwikSymbolTrackerWindow, d, l, n, p, r, S) => {
9588
/* eslint-disable no-var -- better minification */
9689
var publicApiKey = __QI_KEY__,
9790
postUrl = __QI_URL__,
98-
getAttribute_s = 'getAttribute' as const,
99-
querySelector_s = 'querySelector' as const,
100-
manifest_s = 'manifest' as const,
101-
manifest_hash_s = `${manifest_s}-hash` as const,
102-
manifestHash_s = `${manifest_s}Hash` as const,
103-
version_s = 'version' as const,
104-
publicApiKey_s = 'publicApiKey' as const,
105-
sendBeacon_s = 'sendBeacon' as const,
106-
symbol_s = 'symbol' as const,
107-
length_s = 'length' as const,
108-
addEventListener_s = 'addEventListener' as const,
109-
route_s = 'route' as const,
110-
error_s = 'error' as const,
111-
stack_s = 'stack' as const,
112-
message_s = 'message' as const,
113-
symbols_s = `${symbol_s}s` as const,
114-
qVersion =
115-
document[querySelector_s](`[q\\:${version_s}]`)?.[getAttribute_s](`q:${version_s}`) ||
116-
'unknown',
91+
qVersion = d.querySelector(`[q\\:version]`)?.getAttribute(`q:version`) || 'unknown',
11792
manifestHash =
118-
document[querySelector_s](`[q\\:${manifest_hash_s}]`)?.[getAttribute_s](
119-
`q:${manifest_hash_s}`
120-
) || 'dev',
93+
d.querySelector(`[q\\:manifest-hash]`)?.getAttribute(`q:manifest-hash`) || 'dev',
12194
qSymbols: InsightSymbol[] = [],
12295
existingSymbols: Set<string> = new Set(),
12396
flushSymbolIndex: number = 0,
12497
lastReqTime: number = 0,
12598
timeoutID: ReturnType<typeof setTimeout> | undefined,
126-
qRouteChangeTime = performance.now(),
127-
qRouteEl = document[querySelector_s](`[q\\:${route_s}]`),
99+
qRouteChangeTime = p.now(),
100+
qRouteEl = d.querySelector(`[q\\:route]`),
128101
flush = () => {
129102
timeoutID = undefined;
130-
if (qSymbols[length_s] > flushSymbolIndex) {
103+
if (qSymbols.length > flushSymbolIndex) {
131104
var payload = {
132105
qVersion,
133-
[publicApiKey_s]: publicApiKey,
134-
[manifestHash_s]: manifestHash,
106+
publicApiKey,
107+
manifestHash,
135108
previousSymbol:
136-
flushSymbolIndex == 0 ? undefined : qSymbols[flushSymbolIndex - 1][symbol_s],
137-
[symbols_s]: qSymbols.slice(flushSymbolIndex),
109+
flushSymbolIndex == 0 ? undefined : qSymbols[flushSymbolIndex - 1].symbol,
110+
symbols: qSymbols.slice(flushSymbolIndex),
138111
} satisfies InsightsPayload;
139-
navigator[sendBeacon_s](postUrl, JSON_stringify(payload));
140-
flushSymbolIndex = qSymbols[length_s];
112+
n.sendBeacon(postUrl, S(payload));
113+
flushSymbolIndex = qSymbols.length;
141114
}
142115
},
143116
debounceFlush = () => {
144117
timeoutID != undefined && clearTimeout(timeoutID);
145118
timeoutID = setTimeout(flush, 1000);
146119
};
147120

148-
window.qSymbolTracker = {
149-
[symbols_s]: qSymbols,
150-
[publicApiKey_s]: publicApiKey,
121+
w.qSymbolTracker = {
122+
symbols: qSymbols,
123+
publicApiKey,
151124
};
152125
if (qRouteEl) {
153126
new MutationObserver((mutations) => {
154-
var mutation = mutations.find((m) => m.attributeName === `q:${route_s}`);
127+
var mutation = mutations.find((m) => m.attributeName === `q:route`);
155128
if (mutation) {
156-
qRouteChangeTime = performance.now();
129+
qRouteChangeTime = p.now();
157130
}
158131
}).observe(qRouteEl, { attributes: true });
159132
}
160-
document[addEventListener_s](
161-
'visibilitychange',
162-
() => document.visibilityState === 'hidden' && flush()
163-
);
164-
document[addEventListener_s](`q${symbol_s}`, (_event) => {
133+
d.addEventListener('visibilitychange', () => d.visibilityState === 'hidden' && flush());
134+
d.addEventListener(`qsymbol`, (_event) => {
165135
var event = _event as CustomEvent<QSymbolDetail>,
166136
detail = event.detail,
167137
symbolRequestTime = detail.reqTime,
168138
symbolDeliveredTime = event.timeStamp,
169-
symbol = detail[symbol_s];
139+
symbol = detail.symbol;
170140
if (!existingSymbols.has(symbol)) {
171141
existingSymbols.add(symbol);
172-
var route = qRouteEl?.[getAttribute_s](`q:${route_s}`) || '/';
142+
var route = qRouteEl?.getAttribute(`q:route`) || '/';
173143
qSymbols.push({
174-
[symbol_s]: symbol,
175-
[route_s]: route,
176-
delay: round(0 - lastReqTime + symbolRequestTime),
177-
latency: round(symbolDeliveredTime - symbolRequestTime),
178-
timeline: round(0 - qRouteChangeTime + symbolRequestTime),
144+
symbol,
145+
route,
146+
delay: r(0 - lastReqTime + symbolRequestTime),
147+
latency: r(symbolDeliveredTime - symbolRequestTime),
148+
timeline: r(0 - qRouteChangeTime + symbolRequestTime),
179149
interaction: !!detail.element,
180150
});
181151
lastReqTime = symbolDeliveredTime;
182152
debounceFlush();
183153
}
184154
});
185-
window[addEventListener_s](error_s, (event: ErrorEvent) => {
186-
var error = event[error_s];
155+
w.addEventListener('error', (event: ErrorEvent) => {
156+
var error = event.error;
187157
if (!(error && typeof error === 'object')) {
188158
return;
189159
}
190160
var payload = {
191-
url: `${location}`,
192-
[manifestHash_s]: manifestHash,
161+
url: `${l}`,
162+
manifestHash,
193163
timestamp: new Date().getTime(),
194164
source: event.filename,
195165
line: event.lineno,
196166
column: event.colno,
197-
[message_s]: event[message_s],
198-
[error_s]: message_s in error ? (error as Error)[message_s] : `${error}`,
199-
[stack_s]: stack_s in error ? (error as Error)[stack_s] || '' : '',
167+
message: event.message,
168+
error: 'message' in error ? (error as Error).message : `${error}`,
169+
stack: 'stack' in error ? (error as Error).stack || '' : '',
200170
} satisfies InsightsError;
201-
navigator[sendBeacon_s](`${postUrl}${error_s}/`, JSON_stringify(payload));
171+
n.sendBeacon(`${postUrl}error/`, S(payload));
202172
});
203173
})(window as any, document, location, navigator, performance, Math.round, JSON.stringify)
204174
);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { expect, test } from 'vitest';
2+
import { insightsPing } from './insights';
3+
import compress from 'brotli/compress.js';
4+
5+
test('insightsPing size', () => {
6+
const pingSrc = (insightsPing as any).resolved.serialized;
7+
const compressed = compress(Buffer.from(pingSrc), { mode: 1, quality: 11 });
8+
9+
expect(compressed.length).toBe(792);
10+
expect(pingSrc.length).toBe(2099);
11+
// Just to a sanity check
12+
expect(pingSrc).toMatchInlineSnapshot(
13+
`"()=>((w,d,l,n,p,r,S)=>{var publicApiKey=__QI_KEY__,postUrl=__QI_URL__,qVersion=d.querySelector(\`[q\\\\:version]\`)?.getAttribute(\`q:version\`)||"unknown",manifestHash=d.querySelector(\`[q\\\\:manifest-hash]\`)?.getAttribute(\`q:manifest-hash\`)||"dev",qSymbols=[],existingSymbols=new Set,flushSymbolIndex=0,lastReqTime=0,timeoutID,qRouteChangeTime=p.now(),qRouteEl=d.querySelector(\`[q\\\\:route]\`),flush=()=>{timeoutID=undefined;if(qSymbols.length>flushSymbolIndex){var payload={qVersion,publicApiKey,manifestHash,previousSymbol:flushSymbolIndex==0?undefined:qSymbols[flushSymbolIndex-1].symbol,symbols:qSymbols.slice(flushSymbolIndex)};n.sendBeacon(postUrl,S(payload));flushSymbolIndex=qSymbols.length;}},debounceFlush=()=>{timeoutID!=undefined&&clearTimeout(timeoutID);timeoutID=setTimeout(flush,1e3);};w.qSymbolTracker={symbols:qSymbols,publicApiKey};if(qRouteEl){new MutationObserver(mutations=>{var mutation=mutations.find(m=>m.attributeName===\`q:route\`);if(mutation){qRouteChangeTime=p.now();}}).observe(qRouteEl,{attributes:true});}d.addEventListener("visibilitychange",()=>d.visibilityState==="hidden"&&flush());d.addEventListener(\`qsymbol\`,_event=>{var event=_event,detail=event.detail,symbolRequestTime=detail.reqTime,symbolDeliveredTime=event.timeStamp,symbol=detail.symbol;if(!existingSymbols.has(symbol)){existingSymbols.add(symbol);var route=qRouteEl?.getAttribute(\`q:route\`)||"/";qSymbols.push({symbol,route,delay:r(0-lastReqTime+symbolRequestTime),latency:r(symbolDeliveredTime-symbolRequestTime),timeline:r(0-qRouteChangeTime+symbolRequestTime),interaction:!!detail.element});lastReqTime=symbolDeliveredTime;debounceFlush();}});w.addEventListener("error",event=>{var error=event.error;if(!(error&&typeof error==="object")){return;}var payload={url:\`\${l}\`,manifestHash,timestamp:new Date().getTime(),source:event.filename,line:event.lineno,column:event.colno,message:event.message,error:"message"in error?error.message:\`\${error}\`,stack:"stack"in error?error.stack||"":""};n.sendBeacon(\`\${postUrl}error/\`,S(payload));});})(window,document,location,navigator,performance,Math.round,JSON.stringify)"`
14+
);
15+
});

packages/qwik/src/insights/qwik.insights.api.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
```ts
66

77
import { Component } from '@qwik.dev/core';
8+
import { SyncQRL } from '@qwik.dev/core';
89

910
// @beta (undocumented)
1011
export const Insights: Component< {
@@ -42,6 +43,11 @@ export interface InsightsPayload {
4243
symbols: InsightSymbol[];
4344
}
4445

46+
// Warning: (ae-internal-missing-underscore) The name "insightsPing" should be prefixed with an underscore because the declaration is marked as @internal
47+
//
48+
// @internal (undocumented)
49+
export const insightsPing: SyncQRL<() => void>;
50+
4551
// @public (undocumented)
4652
export interface InsightSymbol {
4753
delay: number;

scripts/submodule-insights.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ async function buildComponents(config: BuildConfig) {
2323
outDir: distBase,
2424
emptyOutDir: false,
2525
target: 'es2020',
26-
minify: false,
26+
minify: true,
2727
rollupOptions: {
2828
external: (id) => /^(@|node:)/i.test(id),
2929
},

0 commit comments

Comments
 (0)