fix: replace typeof window with typeof document for Node.js 25+ SSR compatibility - #393
fix: replace typeof window with typeof document for Node.js 25+ SSR compatibility#393EduardF1 wants to merge 1 commit into
Conversation
9a159e3 to
841f74d
Compare
SummarySwaps Status
@pacocoursey happy to add more tests or adjust anything if needed. Thanks! |
|
Friendly bump on this fix for Node.js 25+ compatibility. CI is green and it's ready whenever you have time. Thank you! |
|
Hi! Just checking in on this — happy to address any feedback. Thanks! |
|
Pushed a deterministic regression test ( |
Node.js 25 exposes window as an alias for globalThis, which makes the previous typeof window SSR guard take the browser path during server rendering. Use typeof document instead and cover the Node.js 25 server case with a regression test that verifies server rendering does not read localStorage. Fixes pacocoursey#389
999163f to
e9e6e07
Compare
Problem
Node.js 25+ ships an experimental Web Storage API that aliases
windowtoglobalThis. This breaksnext-themeson Node.js 25+ because the SSR guard evaluates at module load time:This causes:
isServer = falseon the servergetTheme()callslocalStorage.getItem()on the serverThemeScriptnonce rendered empty during SSRTypeError: localStorage.getItem is not a functionon startupReported in #389.
Fix
Replace
typeof window === 'undefined'withtypeof document === 'undefined'.documentis a browser-only API — Node.js does not expose it, even in v25+. This is a reliable cross-version SSR guard:Changes
next-themes/src/index.tsx— 2 occurrences updatedTesting
Tested on Node.js v24.15.0, pnpm v10.32.1.