在Next.js中使用Glide JS时出现document is not defined错误
解决Next.js中GlideJS的"ReferenceError: document is not defined"错误
问题原因
Next.js默认采用服务端渲染(SSR),服务端运行在Node.js环境中,没有浏览器提供的DOM对象(比如document)。你当前的Glide.js组件直接在模块顶层执行了依赖document的代码,这段代码会在服务端渲染阶段被执行,因此触发错误。
解决方案
方案1:使用React useEffect钩子(推荐)
将Glide的初始化逻辑放到useEffect中,该钩子的回调函数只会在客户端组件挂载完成后执行,此时DOM已经存在。
修改components/Glide.js为React组件:
import Glide from '@glidejs/glide'; import { useEffect } from 'react'; export default function GlideSlider() { useEffect(() => { // 初始化所有Glide轮播 const sliders = document.querySelectorAll('.glide'); const glideInstances = []; sliders.forEach(slider => { const glide = new Glide(slider, { startAt: 0, autoplay: 2800, hoverpause: true, }); glide.mount(); glideInstances.push(glide); }); // 组件卸载时销毁实例,避免内存泄漏 return () => { glideInstances.forEach(instance => instance.destroy()); }; }, []); // 空依赖数组确保初始化只执行一次 return null; // 无需返回DOM结构,轮播HTML已在页面中定义 }
修改pages/index.js,在轮播DOM后引入该组件:
import GlideSlider from "./components/Glide" export default function Home() { return( <> <div className="glide-container"> <div className="glide"> <div data-glide-el="controls" > <button data-glide-dir="<" className="glide__arrow glide__arrow--left"><</button> <button data-glide-dir=">" className="glide__arrow glide__arrow--right">></button> </div> <div className="glide__track" data-glide-el="track"> <ul className="glide__slides"> <li className="glide__slide"><img src="1.jpg" />1</li> <li className="glide__slide"><img src="2.png" />2</li> <li className="glide__slide"><img src="3.png" />3</li> <li className="glide__slide"><img src="4.png" />4</li> </ul> </div> <div className="glide__bullets" data-glide-el="controls[nav]"> <button className="glide__bullet" data-glide-dir="=0"></button> <button className="glide__bullet" data-glide-dir="=1"></button> <button className="glide__bullet" data-glide-dir="=2"></button> <button className="glide__bullet" data-glide-dir="=3"></button> </div> </div> </div> <GlideSlider /> </> ) }
方案2:动态导入并禁用SSR
使用Next.js的dynamic函数导入Glide组件,强制该组件仅在客户端加载,避免服务端执行DOM相关代码。
修改pages/index.js的导入逻辑:
import dynamic from 'next/dynamic'; // 禁用SSR,仅在客户端加载Glide组件 const Glide = dynamic(() => import('./components/Glide'), { ssr: false }); export default function Home() { // 页面DOM结构保持不变 return( <> <div className="glide-container"> {/* 轮播DOM结构与原代码一致 */} </div> <Glide /> </> ) }
修改components/Glide.js,增加环境判断确保仅在客户端执行:
import Glide from '@glidejs/glide'; // 仅在客户端环境执行初始化 if (typeof document !== 'undefined') { const sliders = document.querySelectorAll('.glide'); for (let i = 0; i < sliders.length; i++) { const glide = new Glide(sliders[i], { startAt: 0, autoplay: 2800, hoverpause: true, }); glide.mount(); } }
额外注意事项
- 必须引入Glide的CSS文件,否则轮播样式异常。在
pages/_app.js中添加:import '@glidejs/glide/dist/css/glide.core.min.css'; import '@glidejs/glide/dist/css/glide.theme.min.css'; - 方案1中添加的实例销毁逻辑,可避免页面切换时的内存泄漏问题。
内容的提问来源于stack exchange,提问作者Esteban Gorupicz
相关产品推荐
相关产品推荐

