From 1037456aa30b59fa5208299185ee788d11e848fb Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Sat, 12 Sep 2026 05:22:59 -0400 Subject: [PATCH] perf(studio): request the player chunk before the shell's first layout The dynamic import of @hyperframes/player ran inside the preview's mount effect, which React schedules after the shell's first layout. On a cold open that layout stalls the main thread for seconds, so the chunk request waited behind it for no reason. The import is now kicked at module scope, behind a typeof window guard that preserves the documented SSR contract (the module registers a custom element at load), and the mount effect awaits the already-in-flight promise. Verified in the built bundle: the preload call sits at module top level, so the request goes out on bundle evaluation. --- packages/studio/src/player/components/Player.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/studio/src/player/components/Player.tsx b/packages/studio/src/player/components/Player.tsx index 50ca3794ee..0eb81e64cf 100644 --- a/packages/studio/src/player/components/Player.tsx +++ b/packages/studio/src/player/components/Player.tsx @@ -5,8 +5,10 @@ import { useMountEffect } from "../../hooks/useMountEffect"; import { applyPreviewVariablesToUrl } from "../../hooks/previewVariablesStore"; import { HyperframesLoader } from "../../components/ui"; // NOTE: importing "@hyperframes/player" registers a class extending HTMLElement -// at module load, which throws under SSR. Defer the import to the mount effect -// so it only runs in the browser. +// at module load, which throws under SSR — hence the dynamic import behind a +// `typeof window` guard. Kicking it at module scope rather than in the mount +// effect puts the chunk request in flight before the shell's first layout. +const playerModule = typeof window === "undefined" ? null : import("@hyperframes/player"); interface PlayerProps { projectId?: string; @@ -166,8 +168,7 @@ export const Player = forwardRef( let canceled = false; let cleanup: (() => void) | undefined; - // Dynamic import registers the custom element in the browser only. - import("@hyperframes/player").then(() => { + playerModule?.then(() => { if (canceled) return; // Create the web component imperatively to avoid JSX custom-element typing.