Skip to content

Commit 65df869

Browse files
Lms24kamilogorek
andauthored
fix(sveltekit): Avoid invalidating data on route changes in wrapServerLoadWithSentry (#8801)
The SvelteKit SDK caused server load data to be invalidated, resulting in said functions being called on every route change. I initially thought this was related to our Kit-specific client fetch instrumentation which turned out not to be causing this. Instead, the culprit is our `wrapServerLoadWithSentry` wrapper: In the wrapper, we access `event.route.id` to determine the route of the load function for the span description. Internally, SvelteKit puts a proxy on certain `event` properties, such as `event.route`. In case any property of `event.route` was accessed, [SvelteKit marks this](https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/server/page/load_data.js#L111-L124) internally and send along a flag to the client. On a route change, the client would [check this flag](https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/client/client.js#L572) and mark the route as invalidated, thereby causing a [call to the load function](https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/client/client.js#L641) on each navigation. --------- Co-authored-by: Kamil Ogórek <[email protected]>
1 parent dc653d0 commit 65df869

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

packages/sveltekit/src/server/load.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ export function wrapServerLoadWithSentry<T extends (...args: any) => any>(origSe
119119

120120
addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
121121

122-
const routeId = event.route && event.route.id;
122+
// Accessing any member of `event.route` causes SvelteKit to invalidate the
123+
// server `load` function's data on every route change.
124+
// To work around this, we use `Object.getOwnPropertyDescriptor` which doesn't invoke the proxy.
125+
// https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/server/page/load_data.js#L111C3-L124
126+
const routeId = event.route && (Object.getOwnPropertyDescriptor(event.route, 'id')?.value as string | undefined);
123127

124128
const { dynamicSamplingContext, traceparentData, propagationContext } = getTracePropagationData(event);
125129
getCurrentHub().getScope().setPropagationContext(propagationContext);

packages/sveltekit/test/server/load.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,33 @@ describe('wrapServerLoadWithSentry calls trace', () => {
400400

401401
expect(mockTrace).toHaveBeenCalledTimes(1);
402402
});
403+
404+
it("doesn't invoke the proxy set on `event.route`", async () => {
405+
const event = getServerOnlyArgs();
406+
407+
// simulates SvelteKit adding a proxy to `event.route`
408+
// https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/server/page/load_data.js#L111C3-L124
409+
const proxyFn = vi.fn((target: { id: string }, key: string | symbol): any => {
410+
return target[key];
411+
});
412+
413+
event.route = new Proxy(event.route, {
414+
get: proxyFn,
415+
});
416+
417+
const wrappedLoad = wrapServerLoadWithSentry(serverLoad);
418+
await wrappedLoad(event);
419+
420+
expect(mockTrace).toHaveBeenCalledTimes(1);
421+
expect(mockTrace).toHaveBeenCalledWith(
422+
expect.objectContaining({
423+
op: 'function.sveltekit.server.load',
424+
name: '/users/[id]', // <-- this shows that the route was still accessed
425+
}),
426+
expect.any(Function),
427+
expect.any(Function),
428+
);
429+
430+
expect(proxyFn).not.toHaveBeenCalled();
431+
});
403432
});

0 commit comments

Comments
 (0)