Next.js 56: next/dynamic — Code Splitting
easy⏱ 5 mincoursenextjs
Same idea, browser-only extras
React.lazy(() => import(...)) returns a component that resolves asynchronously; wrapping it in Suspense fallback={...} shows a placeholder while the code downloads. next/dynamic wraps exactly this pattern and adds ssr: false, which skips server rendering entirely for components that only make sense in a browser (they touch window, a canvas, a map library, etc.).
import dynamic from "next/dynamic";
const HeavyChart = dynamic(() => import("./HeavyChart"), {
ssr: false,
loading: () => <p>Loading chart...</p>,
});
export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<HeavyChart />
</div>
);
}
Defer a second widget
HeavyMapImpl is now wrapped in a lazy(() => new Promise(...)) call named HeavyMap — the same fake-import-via-Promise trick used for HeavyChart — and rendered inside its own Suspense boundary. Click 'Show map' and watch its own loading fallback appear before the map does.
Bundle size vs perceived speed
Every component you defer shrinks the JavaScript the browser must parse before your page becomes interactive. The tradeoff: the first time a deferred component is shown, there is a brief loading state while its code downloads. For rarely-used, heavy pieces (rich text editors, charts, maps) that tradeoff is almost always worth it.