Next.js 13使用bulma-calendar遇window未定义问题求助
Next.js 13 解决 bulma-calendar 服务端执行导致
window is not defined 错误问题 问题背景
使用Next.js 13集成bulma-calendar时,出现服务端渲染报错:ReferenceError: window is not defined。原因是bulma-calendar在导入阶段就会执行依赖window的初始化代码,即使将初始化逻辑放在useEffect中,全页刷新时服务端仍会执行导入操作导致报错;仅代码修改触发快速刷新时正常,因为此时客户端已加载完成。尝试用next/script加载库,但无法直接从node_modules打包脚本,且加载后无法获取bulmaCalendar变量。
解决方案(无需手动处理脚本文件)
1. 动态导入(推荐)
利用Next.js的动态导入特性,将bulma-calendar的加载推迟到客户端执行,避免服务端触发依赖window的代码。
import React, { useEffect } from 'react'; const Sample = () => { useEffect(() => { const initCalendar = async () => { // 仅在客户端动态导入库 const bulmaCalendarModule = await import('bulma-calendar/dist/js/bulma-calendar.min.js'); bulmaCalendarModule.default.attach('#calendar', {}); }; initCalendar(); }, []); return ( <main> <form> <input id="calendar" type="date" /> </form> </main> ); }; export default Sample;
2. 客户端组件标记(App Router 专属)
如果使用Next.js 13 App Router,在组件顶部添加'use client'指令,强制整个组件仅在客户端渲染,所有导入和代码逻辑都不会在服务端执行。
'use client'; import React, { useEffect } from 'react'; import bulmaCalendar from 'bulma-calendar/dist/js/bulma-calendar.min.js'; const Sample = () => { useEffect(() => { bulmaCalendar.attach('#calendar', {}); }, []); return ( <main> <form> <input id="calendar" type="date" /> </form> </main> ); }; export default Sample;
3. 同步加载结合客户端环境判断
使用require在useEffect内同步加载库,同时通过typeof window !== 'undefined'确保仅在客户端执行。
import React, { useEffect } from 'react'; const Sample = () => { useEffect(() => { if (typeof window !== 'undefined') { const bulmaCalendar = require('bulma-calendar/dist/js/bulma-calendar.min.js'); bulmaCalendar.default.attach('#calendar', {}); } }, []); return ( <main> <form> <input id="calendar" type="date" /> </form> </main> ); }; export default Sample;
原理说明
- 动态导入:通过
await import()让模块加载逻辑仅在客户端useEffect中执行,服务端不会处理该导入操作。 - 客户端组件标记:
'use client'告诉Next.js该组件无需服务端渲染,所有代码都在浏览器环境中运行,自然可以访问window。 - 环境判断:通过检查
window是否存在,确保依赖浏览器环境的代码仅在客户端执行,避免服务端报错。
内容的提问来源于stack exchange,提问作者Роман Коптев
相关产品推荐
相关产品推荐

