
在 Next.js 13 中导入控制器类时出现 ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization,本质是 Webpack 构建阶段对循环依赖的严格校验所致;而 CRA 因配置差异暂未暴露该问题,需重构模块关系以彻底规避。
在 next.js 13 中导入控制器类时出现 `referenceerror: cannot access '__webpack_default_export__' before initialization`,本质是 webpack 构建阶段对循环依赖的严格校验所致;而 cra 因配置差异暂未暴露该问题,需重构模块关系以彻底规避。
Next.js(尤其是 App Router)采用更严格的模块解析策略,其底层 Webpack 构建器对循环依赖(circular dependencies) 的容忍度远低于 Create React App(CRA)。你描述的架构——MyObject extends BusinessObject,而 BusinessObject 又在构造函数中实例化 DataAccessObject,若其中任一模块反向引用了调用方(例如 DataAccessObject 导入了某个业务模型,而该模型又间接依赖 BusinessObject),就会触发 Webpack 的“未初始化导出访问”错误。这并非 Next.js 的 Bug,而是现代构建工具对模块健康性的主动拦截。
? 为什么 CRA 能运行而 Next.js 报错?
- CRA 使用较宽松的 Webpack 配置(如
module.noParse或默认忽略部分循环),且主要面向客户端渲染,模块解析时机与服务端逻辑分离; - Next.js App Router 同时支持 SSR/SSG/Edge Runtime,要求模块在服务端首次加载时即具备确定性导出顺序,对依赖图的拓扑排序更为严格;
- 错误信息
__WEBPACK_DEFAULT_EXPORT__明确指向 Webpack 的 ESM 处理机制——当模块 A 尚未完成export default初始化,模块 B 却已通过静态import尝试访问它,即被拒绝。
✅ 正确解决方案:解耦 + 延迟初始化
避免在类构造函数中直接实例化强依赖项,改用依赖注入或工厂模式:
// ✅ 推荐:将 DataAccessObject 作为参数传入,而非构造函数内 new
class BusinessObject {
protected dao: DataAccessObject;
constructor(dao: DataAccessObject) {
this.dao = dao; // 依赖由外部注入,消除隐式循环
}
}
class MyObject extends BusinessObject {
constructor(dao: DataAccessObject) {
super(dao);
}
async getData() {
return this.dao.find({}); // 方法内调用,非构造时绑定
}
}
// API Route (/app/api/my-object/route.ts)
import { MyObject } from '@monorepo/controllers/MyObject';
import { MongoDBDAO } from '@monorepo/data-access/mongodb';
export async function GET() {
const dao = new MongoDBDAO(); // 实例化置于运行时
const controller = new MyObject(dao); // 依赖明确、无静态导入链
const data = await controller.getData();
return Response.json(data);
}
⚠️ 关键注意事项
-
禁止在顶层或构造函数中跨模块静态导入形成闭环:检查
BusinessObject、DataAccessObject及其子类是否相互import; -
绝对路径别名(
@monorepo/...)本身不引发问题,但会掩盖依赖路径:使用npx tsc --noEmit --watch或depcheck工具扫描真实依赖环; -
不要用
require()替代import作为临时方案:虽可能绕过错误,但破坏 ESM 语义、丧失 Tree Shaking,且在 Edge Runtime 中不可用; -
优先采用组合优于继承:考虑将
BusinessObject改为可复用的 Hook 或 Service 类,通过组合注入 DAO,而非继承链式耦合。
? 总结:该错误是模块设计发出的健康预警。Next.js 的严格性恰恰帮助你提前发现潜在的架构脆弱点。重构目标不是“让代码跑起来”,而是建立清晰、单向、可测试的依赖流——这才是企业级应用长期可维护的基石。











