Next.js使用masonry-layout报错:ReferenceError: window is not defined
解决Next.js中masonry-layout/packery的「window is not defined」错误
问题根源是Next.js的服务端渲染(SSR)机制:服务端环境没有window对象,而masonry、packery这类库依赖浏览器环境,直接导入会在服务端执行阶段触发错误,导致部署失败。以下是几种可靠的解决方法:
方法1:使用Next.js动态导入(推荐)
通过next/dynamic动态导入包含masonry的组件,并禁用SSR,确保组件只在客户端加载:
// 页面文件中 import dynamic from 'next/dynamic'; // 动态导入你的瀑布流组件,禁用SSR const MasonryGrid = dynamic(() => import('../components/MasonryGrid'), { ssr: false, loading: () => <div>加载中...</div> // 可选的加载占位符 }); export default function Home() { return ( <div> <MasonryGrid /> </div> ); }
在你的MasonryGrid组件中正常使用masonry即可:
// components/MasonryGrid.jsx import { useEffect, useRef } from 'react'; import Masonry from 'masonry-layout'; export default function MasonryGrid() { const gridRef = useRef(null); useEffect(() => { const masonryInstance = new Masonry(gridRef.current, { itemSelector: '.grid-item', columnWidth: 200, gutter: 15 }); // 组件卸载时销毁实例 return () => masonryInstance.destroy(); }, []); return ( <div className="grid" ref={gridRef}> <div className="grid-item">内容1</div> <div className="grid-item">内容2</div> {/* 更多瀑布流项 */} </div> ); }
方法2:在客户端生命周期中初始化库
利用React的useEffect钩子(仅在客户端执行),在确认window存在后再初始化masonry/packery:
import { useEffect, useRef } from 'react'; export default function PackeryGrid() { const containerRef = useRef(null); useEffect(() => { // 确保仅在客户端环境执行 if (typeof window === 'undefined' || !containerRef.current) return; // 动态导入packery(避免服务端加载) import('packery') .then(({ default: Packery }) => { const packeryInstance = new Packery(containerRef.current, { itemSelector: '.packery-item', gutter: 10 }); return () => packeryInstance.destroy(); }); }, []); return ( <div className="packery-container" ref={containerRef}> <div className="packery-item">内容A</div> <div className="packery-item">内容B</div> </div> ); }
为什么修改node_modules无效?
你修改node_modules中的代码不会被版本控制系统追踪,部署时Netlify会重新安装依赖包,你的修改会被覆盖。而且直接修改第三方库源码会导致后续依赖更新时丢失更改,是不可持续的解决方案。
内容的提问来源于stack exchange,提问作者Mayowa
相关产品推荐
相关产品推荐

