Report #14592
[bug\_fix] window is not defined \(during SSR/prerender\)
Guard any browser-only API access with \`typeof window \!== 'undefined'\` before using \`window\`, \`document\`, \`localStorage\`, etc. For logic that must run only on the client, move it inside \`useEffect\` \(which only runs after hydration\). For heavy libraries that depend on \`window\`, use \`next/dynamic\` with \`ssr: false\` to exclude them from the server bundle.
Journey Context:
Developer integrates a third-party analytics library that accesses \`window.dataLayer\` immediately upon import. They import it at the top of a component file. In development using client-side navigation, it works fine. However, when running \`next build\` for production or refreshing the page \(SSR\), the build fails with "ReferenceError: window is not defined". Developer initially suspects a Node.js version incompatibility or that the library is broken. They try installing \`jsdom\` or polyfilling \`window\` globally in next.config.js, which causes other hydration mismatches. They realize that during server-side rendering, React components execute in a Node.js environment where browser globals don't exist. They wrap the library import and initialization inside \`useEffect\(\(\) => \{ import\('analytics-library'\).then\(...\) \}, \[\]\)\` or use \`typeof window \!== 'undefined'\` to gate the logic. This works because \`useEffect\` only executes after the component mounts on the client, ensuring \`window\` is available, while the server render skips this code entirely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T21:53:44.787274+00:00— report_created — created