# 关于 exports is not defined 报错的乱解,最后解决了问题
参考文献
一篇文章搞清楚 exports is not defined 为什么又出现了 https://github.com/natsu0728/blog/issues/22
# 原因
导致这个 exports is not defined
问题的理由有很多种,但是原因只有一个:
直接上原因:webpack 没有识别出 CommonJs 写法的模块
JS 的模块系统主要分为 CommonJS
和 ES modules
(区别看最下面拓展)
抱怨一下,这个问题我花了一天时间来找解决方案,有点恼火,主要是对 Webpack 使用和编译原理不熟悉
说一下我的报错产生的情景
- 采用 vue-cli 搭建项目
- 使用 webpack 开发模式-采用热更新
- webpack 编译时未报错,运行到浏览器输出了报错
此文分析得出的解决方案,仅对此文情形有效,若对你的项目无效,还需要自行具体分析, 可参考 一篇文章搞清楚 exports is not defined 为什么又出现了 (opens new window)
# 报错分析
# 报错日志
index.mjs:9 Uncaught ReferenceError: exports is not defined
at ./node_modules/normalize-wheel-es/dist/index.mjs (index.mjs:9:1)
at __webpack_require__ (bootstrap:22:1)
at fn (hot module replacement:61:1)
at ./node_modules/element-plus/lib/directives/mousewheel/index.js (index.ts:66:1)
at __webpack_require__ (bootstrap:22:1)
at fn (hot module replacement:61:1)
at ./node_modules/element-plus/lib/directives/index.js (index.ts:66:1)
at __webpack_require__ (bootstrap:22:1)
at fn (hot module replacement:61:1)
at ./node_modules/element-plus/lib/components/time-picker/src/time-picker-com/basic-time-spinner.js
2
3
4
5
6
7
8
9
10
11
看第一行, 这里指出了 exports is not defined
是由于在引入 ./node_modules/normalize-wheel-es/dist/index.mjs (index.mjs:9:1)
文件时报错的
index.mjs:9 Uncaught ReferenceError: exports is not defined
at ./node_modules/normalize-wheel-es/dist/index.mjs (index.mjs:9:1)
2
index.mjs
是一个 JS 文件,但是 .mjs
的后缀说明他本身是一个采用 ES modules
模块系统语法编写的文件
同理 index.cjs
就是 采用 CommonJS
模块系统语法编写的文件
再看 ./node_modules/normalize-wheel-es/dist/index.mjs (index.mjs:9:1)
说明这是一个依赖的引入
从报错日志调用栈来看 normalize-wheel-es
是 element-plus
调用的,属于 element-plus
的依赖(即依赖的依赖)
我就是在这里卡住的,然后采用了许多连我自己的不清楚的解决方案,依旧不行
所以上面的分析似乎没有什么作用
但是在思考中我还是想到了一个问题:'webpack 在开发模式下的热更新编译采用的 CommonJS 还是 ES Modules 呢?'
热更新的实现主要是插件 webpack-dev-server
提供的
也就是 webpack-dev-server
采用的 CommonJS 还是 ES Module?
很遗憾,网上没有搜到,怎么办
果断问了一下 G 老师
我:webpack-dev-server 采用的 CommonJS 还是 ES Module?
chatgpt:webpack-dev-server 主要使用 CommonJS 模块格式来处理其内部代码。虽然 Webpack 本身支持 ES Modules (import/export),许多与 Webpack 相关的工具和库,包括 webpack-dev-server,仍然使用 CommonJS 格式。
2
3
原来如此,姑且相信 G 老师
去官网的 webpack-dev-server https://webpack.js.org/api/webpack-dev-server/ 介绍中 也说了这么一句话
webpack-dev-server provides a Node.js API which can be used directly in Node.js runtime.
译文:Webpack-dev-server 提供了一个 Node.js API,这个 API 可以直接在 Node.js 运行时中使用。
那 nodejs 本身是采用什么模块系统呢
我:nodejs 支持哪一种 模块系统?
chatgpt:
CommonJS: 这是 Node.js 的默认模块系统。它使用 require() 来导入模块,使用 module.exports 来导出模块。
Node.js 从版本 12 开始支持 ESM(ES Modules),但要完全支持,需要 Node.js 14 及以上版本,并且需要在文件名中使用 .mjs 扩展名,或者在 package.json 中设置 "type": "module"。
2
3
4
5
所以结合两次G老师的答案,猜测webpack 使用 Webpack-dev-server 热更新编译后的代码文件是使用 CommonJS
所以产生报错的链路就是,热更新编译的代码采用CommonJS,但是依赖库的 normalize-wheel-es
提供的是 ES modules的 .mjs
文件,然后就报错了
然后, 就没有然后
我又卡住了
既然 编译后的代码文件使用 CommonJS 模块,而依赖库的 normalize-wheel-es
确实ES modules 文件,该如何解决呢
但是此时瞎猫碰到死耗子
, 编译时采用排除 node_modules
依赖库的办法成功解决了报错
# 解决方案
在 vue.config,js
中手动配置 babel-loader 处理器,并将 node_modules 排除在外
module.exports = {
chainWebpack: (config) => {
// ... 其他配置
// 排除 node_modules 依赖的编译
config.module
.rule("js")
.test(/\.(js|mjs)$/)
.exclude.add(/node_modules/)
.end()
.use("babel-loader") // 修改 babel-loader 的配置选项
.loader("babel-loader")
.tap((options) => {
return {
...options,
presets: ["@babel/preset-env"],
};
});
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 拓展
先要明确的是 exports
本身是 CommonJS 的用法, CommonJS 基础用法如下:
- CommonJS
// 导出
module.exports = { XXX: "HIHI" };
// 导入
const { XXX } = require("/filePath");
2
3
4
5
相对于 CommonJS ,就是 ES modules 模块, ES modules 基础用法如下:
- ES modules
// 用法一: 多个导出,多个导入
// 导出
export {XXX:'HIHI'}
// 导入
import { XXX } from '/filePath'
// 用法二: 整体导出,整体导入
// 导出
export default {XXX:'HIHI'}
// 导入
import YYY from '/filePath'
console.log(YYY.XXX) // 'HIHI'
2
3
4
5
6
7
8
9
10
11
12
13
若有遗漏及错误描述,望指出,接受拷打🤓