feat(studio): enable timeline virtualization by default (#2926)

* feat(studio): enable timeline virtualization by default

* fix(ci): measure timeline performance in production React
This commit is contained in:
Miguel Ángel
2026-07-31 19:43:47 +02:00
committed by GitHub
parent 723d3381c4
commit c6925e471a
13 changed files with 202 additions and 68 deletions
@@ -0,0 +1,35 @@
import { afterEach, describe, expect, it, vi } from "vitest";
afterEach(() => {
vi.unstubAllEnvs();
vi.resetModules();
});
describe("Studio test mode", () => {
it("exposes hooks in the normal development runtime", async () => {
const { STUDIO_RUNTIME_MODE, STUDIO_TEST_HOOKS_ENABLED } = await import("./studioTestMode");
expect(STUDIO_RUNTIME_MODE).toBe("development");
expect(STUDIO_TEST_HOOKS_ENABLED).toBe(true);
});
it("keeps hooks on the development server while it uses production React", async () => {
vi.stubEnv("DEV", false);
vi.stubEnv("MODE", "development");
const { STUDIO_RUNTIME_MODE, STUDIO_TEST_HOOKS_ENABLED } = await import("./studioTestMode");
expect(STUDIO_RUNTIME_MODE).toBe("production");
expect(STUDIO_TEST_HOOKS_ENABLED).toBe(true);
});
it("keeps test hooks out of an ordinary production build", async () => {
vi.stubEnv("DEV", false);
vi.stubEnv("MODE", "production");
const { STUDIO_RUNTIME_MODE, STUDIO_TEST_HOOKS_ENABLED } = await import("./studioTestMode");
expect(STUDIO_RUNTIME_MODE).toBe("production");
expect(STUDIO_TEST_HOOKS_ENABLED).toBe(false);
});
});
@@ -0,0 +1,23 @@
export type StudioRuntimeMode = "development" | "production";
function readStudioImportMetaEnv(): ImportMetaEnv | undefined {
try {
return import.meta.env;
} catch {
return undefined;
}
}
const studioImportMetaEnv = readStudioImportMetaEnv();
/**
* Test hooks belong to Vite's development server, even when that server uses
* production React for performance measurement. A production build has neither
* DEV nor the development server mode, so the API stays out of shipped assets.
*/
export const STUDIO_RUNTIME_MODE: StudioRuntimeMode = studioImportMetaEnv?.DEV
? "development"
: "production";
export const STUDIO_TEST_HOOKS_ENABLED =
studioImportMetaEnv?.DEV === true || studioImportMetaEnv?.MODE === "development";
@@ -85,6 +85,7 @@ describe("timeline performance fixture", () => {
const api = window.__studioTest;
expect(api).toBeDefined();
if (!api) throw new Error("Expected dev Studio test API");
expect(api.runtimeMode).toBe("development");
let notifications = 0;
usePlayerStore.setState({
isPlaying: true,
@@ -12,6 +12,7 @@ import {
type TimelinePerformanceFixtureSummary,
} from "../player/lib/timelinePerformanceFixture";
import { TIMELINE_VIEWPORT_BUDGETS } from "../player/lib/timelineViewportBudgets";
import { STUDIO_RUNTIME_MODE, STUDIO_TEST_HOOKS_ENABLED } from "./studioTestMode";
interface StudioTestHookDeps {
previewIframeRef: React.MutableRefObject<HTMLIFrameElement | null>;
@@ -23,6 +24,7 @@ interface StudioTestHookDeps {
}
interface StudioTestApi {
runtimeMode: typeof STUDIO_RUNTIME_MODE;
selectByDomId: (id: string) => Promise<boolean>;
loadTimelinePerformanceFixture: (
spec: TimelinePerformanceFixtureSpec,
@@ -54,14 +56,9 @@ export function useStudioTestHooks({
}: StudioTestHookDeps): void {
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
let isDev = false;
try {
isDev = import.meta.env.DEV === true;
} catch {
isDev = false;
}
if (!isDev || typeof window === "undefined") return;
if (!STUDIO_TEST_HOOKS_ENABLED || typeof window === "undefined") return;
const api: StudioTestApi = {
runtimeMode: STUDIO_RUNTIME_MODE,
selectByDomId: async (id: string): Promise<boolean> => {
const element = previewIframeRef.current?.contentDocument?.getElementById(id) ?? null;
if (!element) return false;