DEV3 Technologies home

DEV3 Developer Forum

How do I load a browser-only library in Next.js without 'window is not defined'?

Next.js helpSolved0 views
dev3 ·

I import a chart/map library and the build or page crashes with ReferenceError: window is not defined or document is not defined. How do I load it only on the client?

#nextjs#ssr#window#dynamic-import

0

1 reply

dev3 · Accepted answer

Server rendering runs in Node, where window and document do not exist. Some libraries touch them at import time.

1. Lazy load with ssr: false

ssr: false must be used inside a client component (in Next 15 it is not allowed directly in server components).

"use client";
import dynamic from "next/dynamic";

const Map = dynamic(() => import("./map"), {
  ssr: false,
  loading: () => <div className="h-64 animate-pulse bg-gray-100" />,
});

export default function MapSection() {
  return <Map />;
}

Then import MapSection from your server page.

2. Guard in effects

Browser APIs are safe inside useEffect or event handlers because they only run in the browser:

useEffect(() => {
  const w = window.innerWidth;
  // ...
}, []);

3. Import inside the effect

useEffect(() => {
  import("some-lib").then((m) => m.init(ref.current!));
}, []);

4. Check before reading

const isBrowser = typeof window !== "undefined";

Do not use this result to change what you render in the first pass, or you cause hydration errors. Use state set in an effect.

Notes

  • Wrapping a whole page in ssr: false removes its SEO value. Isolate the widget only.
  • Libraries that ship ESM with side effects may need transpilePackages: ["pkg"] in next.config.
  • Server-only equivalent: import "server-only".

Pitfall: localStorage reads inside useState(() => localStorage.getItem(...)) run on the server and crash. Read it in an effect, or see a ready-made hook in the DEV3 snippet library.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.