NextJS CSR项目构建遇jQuery报错:Cannot read properties of undefined (reading 'document')
解决TypeError: Cannot read properties of undefined (reading 'document')问题
问题根源
你加了"use client"没错,但静态导入evo-calendar和jquery的时候,这些库会在模块加载阶段就尝试访问document对象——而Next.js在构建/服务器端预渲染环节根本没有这个浏览器环境,所以直接触发了错误,和你在useEffect里加的document判断没关系,因为那是运行时的判断,导入阶段已经报错了。
解决方法:动态导入依赖
把静态导入改成仅在客户端运行时动态导入,确保这些依赖只在浏览器环境里加载:
修改后的完整代码:
"use client"; import { useEffect } from "react"; import "./custom-calendar.scss"; const Page = () => { useEffect(() => { // 仅在客户端环境下动态导入依赖 const loadCalendar = async () => { if (typeof window === "undefined") return; // 动态导入jQuery和Evo Calendar const $ = (await import("jquery")).default; await import("evo-calendar/evo-calendar/js/evo-calendar.js"); // 初始化日历 const calendar = $("#calendar").evoCalendar({ language: "en", todayHighlight: true, calendarEvents: [ { id: "1", badge: "", name: "", description: "", date: ["September/20/2023"], type: "event", everyYear: false, color: "#63d867", }, ], }); // 组件卸载时清理日历实例,防止内存泄漏 return () => { calendar.evoCalendar("destroy"); }; }; loadCalendar(); }, []); return ( <> <div> <span>lorem</span> </div> <div> <div id="calendar" style={{ height: "100%", width: "100%", }} ></div> </div> </> ); }; export default Page;
关键改动说明
- 删掉了顶部静态导入的
$和evo-calendar,改用import()动态导入,这个函数会返回Promise,确保依赖在浏览器环境下才加载 - 用
typeof window === "undefined"做判断(比判断document更直接,Next.js里服务器端没有window对象) - 增加了卸载时的清理逻辑,调用
evoCalendar("destroy")销毁实例,避免内存泄漏
这样修改后,构建过程中服务器端不会加载这些依赖,也就不会触发document未定义的错误,客户端运行时正常初始化日历。
内容的提问来源于stack exchange,提问作者Kamran Khan
相关产品推荐
相关产品推荐

