Stu Mason
Stu Mason

Activity

StuMason/cleanconnect
TidyLinker.com
TypeScript
Pull Request Opened

PR #142 opened: fix: avoid module-load window access in SSR bundle

Summary

Fixes TIDY-LINKER-32Inertia\Ssr\SsrException: window is not defined on /admin.

Two modules touched window at the top level, so importing them under Node SSR threw before any component could render:

  • resources/js/hooks/use-mobile.tsx created the MediaQueryList eagerly with window.matchMedia(...). It's transitively imported by the admin sidebar, so the SSR build of Admin/Dashboard blew up the moment Node evaluated the chunk (the production stack trace pointed at app-logo-Bh8rFSgu.js:147 — the chunk that bundled this hook).
  • resources/js/echo.ts assigned window.Pusher and window.Echo at module scope. Pulled in via app-header/app-sidebar-headeruse-notificationsuse-echoecho. Same SSR latent bug, would crash any authenticated page once the first one was fixed.

Fix

  • use-mobile.tsx — moved window.matchMedia calls inside the subscribe / getSnapshot callbacks, and supplied getServerSnapshot to useSyncExternalStore so SSR returns false (not mobile) without touching window.
  • echo.ts — wrapped the window.Pusher / new Echo() side effects in if (typeof window !== 'undefined'). Consumer hooks only call echo.private(...) inside useEffect, which never runs server-side, so the API surface is unchanged.

Test plan

  • npm run build:ssr succeeds.
  • Loading the SSR app-logo-* chunk in Node no longer throws window is not defined.
  • POSTing a render request to the freshly-built SSR server for Admin/Dashboard evaluates the component (only failure was a missing prop in the smoke fixture, which proves SSR ran past the original failure point).
  • npm run lint and npm run types pass (only an unrelated pre-existing tsconfig deprecation warning).
  • Verify /admin renders without an SSR exception in production after deploy.

Generated by Claude Code

+26
additions
-20
deletions
2
files changed