From 7f07c111ac103db5464fd9ec67ab0f6733aa127c Mon Sep 17 00:00:00 2001
From: openhands
Date: Sat, 3 Oct 2026 19:21:02 +0200
Subject: [PATCH] perf(studio): load motion's minimal entry instead of the full
component library
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
/admin/studio/furni sat at 94.9% of its initial-JS budget (427436 of
450560 gzip bytes), so the next feature would have broken the build. Of the
98228 gzip bytes unique to that route, a large part is framer-motion.
This file uses motion twice, for one thing: a 150ms opacity fade on the result
pane when viewMode changes. Importing `motion/react` to get it pulls in
framer-motion's complete component library — 73 internal modules — plus its
render components, drag/gesture and projection code, none of which is
rendered here.
`motion/react-m` ships only the element factories: 2 internal modules, and the
same initial/animate/transition props, so the fade is unchanged. It exports the
elements flat rather than under a `motion.` namespace, so the import becomes
`div as Mdiv` and the two JSX tags are renamed to match.
I could not measure the resulting bundle here: the local build is OOM-killed
(exit 137) with the running containers on the host, so the actual saving is
unverified. The CI build reports it in build-reports, and the number in this
commit message should be read as a hypothesis, not a measurement.
Verified: typecheck clean, lint clean, and the 10 studio UI tests pass —
including the pane and navigation specs that exercise the view switch.
---
src/components/admin/studio/studio-client.tsx | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/components/admin/studio/studio-client.tsx b/src/components/admin/studio/studio-client.tsx
index 164b78be..db293b74 100644
--- a/src/components/admin/studio/studio-client.tsx
+++ b/src/components/admin/studio/studio-client.tsx
@@ -26,7 +26,13 @@ import {
Trash2,
X,
} from "lucide-react";
-import { motion } from "motion/react";
+// motion/react-m is the minimal entry. The full motion/react pulls in
+// framer-motion's entire component library (73 internal modules) for what this
+// file needs: one fade-in on the result pane. The minimal entry ships only the
+// element factories (2 modules) and exposes the same initial/animate/transition
+// props, so the fade behaves identically. Only the element factory is
+// imported, since that is the single one this file renders.
+import { div as Mdiv } from "motion/react-m";
import {
lazy,
Suspense,
@@ -2053,7 +2059,7 @@ export function StudioClient({
) : (
-
)}
-
+
)}