如何解决Next.js中Bootstrap引发的ReferenceError: document is not defined错误
解决Next.js中"ReferenceError: document is not defined"(Bootstrap Dropdown相关)
问题根源
Next.js在服务器端渲染(SSR)或静态生成(SSG)阶段运行在Node.js环境,该环境没有浏览器专属的document对象。而你导入的Bootstrap Dropdown JS依赖document,导致服务器端执行时抛出错误。
解决方案
1. 动态导入组件/依赖,禁用SSR
使用Next.js的dynamic函数,将依赖Bootstrap Dropdown的组件设置为仅在客户端渲染,避免服务器端执行相关代码。
方式A:动态导入整个Nav组件
// 在使用Nav的页面或组件中 import dynamic from 'next/dynamic'; const Nav = dynamic(() => import('../components/Nav'), { ssr: false, });
方式B:在Nav组件内部动态加载Dropdown
// Nav组件内部 import { useEffect } from 'react'; function Nav() { useEffect(() => { // 仅在客户端挂载后导入Bootstrap Dropdown import('bootstrap/js/dist/dropdown'); }, []); // 组件其余代码... return <nav>{/* 导航内容 */}</nav>; } export default Nav;
2. 仅在客户端环境加载Bootstrap JS
通过判断window对象是否存在,确保仅在浏览器环境执行Bootstrap的导入逻辑:
// Nav组件内部 import { useEffect } from 'react'; function Nav() { useEffect(() => { if (typeof window !== 'undefined') { // 仅在客户端执行此导入 import('bootstrap/js/dist/dropdown'); } }, []); // 组件其余代码... }
3. 使用React版Bootstrap(react-bootstrap)
放弃直接导入原生Bootstrap JS,改用官方维护的React封装库react-bootstrap,它已适配Next.js的SSR场景:
安装依赖
npm install react-bootstrap bootstrap
导入CSS与使用Dropdown组件
// 在pages/_app.js中全局导入Bootstrap CSS import 'bootstrap/dist/css/bootstrap.min.css'; // 在Nav组件中使用react-bootstrap的Dropdown import { Dropdown } from 'react-bootstrap'; function Nav() { return ( <nav> <Dropdown> <Dropdown.Toggle variant="primary" id="dropdown-nav"> 下拉菜单 </Dropdown.Toggle> <Dropdown.Menu> <Dropdown.Item href="/">首页</Dropdown.Item> <Dropdown.Item href="/about">关于我们</Dropdown.Item> </Dropdown.Menu> </Dropdown> </nav> ); } export default Nav;
4. 全局客户端初始化Bootstrap
如果项目多处使用Bootstrap的JS功能,可在_app.js中通过useEffect在客户端挂载后全局加载Bootstrap:
// pages/_app.js import { useEffect } from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; import '../styles/globals.css'; function MyApp({ Component, pageProps }) { useEffect(() => { // 客户端挂载后加载完整Bootstrap JS import('bootstrap/dist/js/bootstrap.bundle.min.js'); }, []); return <Component {...pageProps} />; } export default MyApp;
这种方式下,无需在单个组件中单独导入Dropdown,Bootstrap会自动初始化页面上的所有交互组件。
选择建议
- 若仅单个组件依赖Dropdown:优先用动态导入(方式1)
- 若项目大量使用Bootstrap组件:推荐用react-bootstrap(方式3),代码更贴合React生态
- 若需全局使用Bootstrap所有JS功能:用全局客户端初始化(方式4)
内容的提问来源于stack exchange,提问作者Winston Harbor
相关产品推荐
相关产品推荐

