feat: reduce first-load JS below 200kB on all pages (#893)#896
feat: reduce first-load JS below 200kB on all pages (#893)#896sw-factory-automations merged 1 commit intomainfrom
Conversation
- Switch auth forms (sign-in, sign-up, forgot-password, reset-password) from direct createClient to lazy getClient, deferring the ~64kB gzipped Supabase SDK to first user interaction - Dynamically import OAuthButtons in sign-in/sign-up forms to keep @floating-ui and @base-ui/react tooltip primitives out of initial load - Extract DeleteWorkspaceSection from WorkspaceSettingsForm and lazy-load it, deferring AlertDialog primitives - Add DangerZoneSettings wrapper to lazy-load DeleteAccountSection - Add WorkspaceHomeClient and MembersPageClient wrappers to defer Select, AlertDialog, Dialog, and Tooltip primitives via next/dynamic Before → After (gzipped first-load JS): /sign-up: 287kB → 187kB /sign-in: 287kB → 187kB /[ws]/settings/members: 265kB → 183kB /[ws]: 242kB → 181kB /[ws]/settings: 224kB → 197kB /reset-password: 247kB → 188kB /forgot-password: 247kB → 188kB Co-authored-by: Ona <no-reply@ona.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
✅ UI verification passed — design spec compliance confirmed. Static analysis: All 10 changed UI files reviewed against Storybook visual regression: No regressions related to this PR. Two pre-existing issues detected (8 missing baselines for Live site screenshots (7 routes, desktop dark + mobile):
All pages use correct dark mode tokens, sharp corners, Tailwind spacing scale, proper typography, and responsive mobile layouts. |
|
✅ Post-merge verification passed. E2E suite (302 passed, 6 failed — all pre-existing):
No new failures introduced by this PR. Ad-hoc smoke tests — all passed:
Interaction smoke tests (feature-specific) — all passed:
|
Closes #893
What
All 11 application pages now load under the 200kB gzipped first-load JS budget. Previously 7 pages exceeded it, with the worst at 287kB.
How
Three techniques applied in order of impact:
1. Lazy Supabase client in auth forms (~64kB saved per auth page)
Auth forms (sign-in, sign-up, forgot-password, reset-password) and OAuthButtons imported
createClientdirectly from@/lib/supabase/client, which statically bundled the full Supabase SDK (~64kB gzipped including storage, realtime, WebSocket, postgrest). Switched to the existinggetClientfrom@/lib/supabase/lazy-client— the SDK loads on first user interaction instead of at page load.2. Dynamic import of OAuthButtons (~40kB saved on sign-in/sign-up)
OAuthButtons imports Tooltip from
@base-ui/reactwhich pulls in@floating-ui/react-dom. Dynamically importing OAuthButtons vianext/dynamicdefers these primitives.3. Client wrappers for workspace pages (37–82kB saved per page)
Server component pages can't use
next/dynamicfor code splitting. Added thin client wrapper components that dynamically import the heavy page-level components:WorkspaceHomeClient→ lazy-loadsWorkspaceHome(Select + @floating-ui)MembersPageClient→ lazy-loadsMembersPage(Select + AlertDialog + Dialog + Tooltip)DangerZoneSettings→ lazy-loadsDeleteAccountSection(AlertDialog)DeleteWorkspaceSectionextracted fromWorkspaceSettingsFormand lazy-loaded (AlertDialog)Results
Testing
pnpm lint✅pnpm typecheck✅pnpm test— 127 files, 1736 tests passed ✅pnpm test:e2e— 297 passed, 9 failed (all pre-existing failures in unrelated areas: database-csv-export, database-inline, favorites, not-found, trash, version-history, workspace-limit) ✅