五一结束,开开心心的上班,结果第一天就给了一个惊喜,原本webpack构建好好地,突然就报了一个错。
错误日志如下
代码语言:javascript复制Can't import the named export 'SetArray' from non EcmaScript module (only default export is available
详细错误日志如下
代码语言:javascript复制[Build] [BABEL] Note: The code generator has deoptimised the styling of /data/auto-ci/wspace/node_modules/lodash/lodash.js as it exceeds the max of 500KB.
[Build] ./node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs 38:20-28
[Build] Can't import the named export 'SetArray' from non EcmaScript module (only default export is available)
[Build] at HarmonyImportSpecifierDependency._getErrors (/data/auto-ci/wspace/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:88:6)
[Build] at HarmonyImportSpecifierDependency.getErrors (/data/auto-ci/wspace/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:68:16)
[Build] at Compilation.reportDependencyErrorsAndWarnings (/data/auto-ci/wspace/node_modules/webpack/lib/Compilation.js:1463:22)
[Build] at /data/auto-ci/wspace/node_modules/webpack/lib/Compilation.js:1258:10
[Build] at AsyncSeriesHook.eval [as callAsync] (eval at create (/data/auto-ci/wspace/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:22:1)
[Build] at AsyncSeriesHook.lazyCompileHook (/data/auto-ci/wspace/node_modules/tapable/lib/Hook.js:154:20)
[Build] at Compilation.finish (/data/auto-ci/wspace/node_modules/webpack/lib/Compilation.js:1253:28)
[Build] at /data/auto-ci/wspace/node_modules/webpack/lib/Compiler.js:672:17
[Build] at _done (eval at create (/data/auto-ci/wspace/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:7:1)
[Build] at eval (eval at create (/data/auto-ci/wspace/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:30:22)
[Build] at /data/auto-ci/wspace/node_modules/webpack/lib/Compilation.js:1185:12
[Build] at /data/auto-ci/wspace/node_modules/webpack/lib/Compilation.js:1097:9
[Build] at processTicksAndRejections (internal/process/task_queues.js:79:11)
[Build] @ ./node_modules/@babel/generator/lib/source-map.js
[Build] @ ./node_modules/@babel/generator/lib/index.js
源码分析
经过一番测试大致锁定了报错范围。
直接报错的位置在 @jridgewell/gen-mapping
这个包,这个包在引入@jridgewell/set-array
而上面错误的详细信息也可以看出就是
Can't import the named export 'SetArray' from non EcmaScript module (only default export is available)
大致意思就是无法导出 SetArray 这个模块。
于是github上找到这两个包的源码
代码语言:javascript复制// @jridgewell/gen-maping/dist/gen-mapping.mjs
import { SetArray, put } from '@jridgewell/set-array';
代码语言:javascript复制// @jridgewell/set-array/dist/set-array.mjs
class SetArray {
constructor() {
this._indexes = { __proto__: null };
this.array = [];
}
}
检查了源码发现并没有什么问题,都是es6的正常语法,至此,似乎没办法往下查了。
重新分析
既然看源码看不出来,那么就从另一个角度来分析一下。
代码语言:javascript复制本地构建正常,服务端构建机报错,项目并没有锁定
这个项目并没有使用 package-lock.json 锁定包版本。
难道是因为 node_modules 的某个依赖包偷偷更新了? 有很大可能是这样。
要验证上面的问题也很简单,直接删掉本地node_modules,重新npm i
安装所有依赖。
果然,重新安装复现了问题了,那么基本就锁定了是版本问题了。
同时也发现了@jridgewell/set-array
这个包是个新包,@jridgewell/gen-mapping
也是最近才引入@jridgewell/set-array
包的。
分析了node_modules内部的互相依赖关系,发现 @babel/* 系列的npm包依赖了@jridgewell/gen-mapping
。
那么很大可能是最近 @babel/* 更新导致的了。
验证猜想
为了验证这个这个猜想,我将package.json 里面所有的@babel/* 包的“^”都去掉(固定版本,不自动安装新包)
代码语言:javascript复制"@babel/******": "^7.10.2"
=>
"@babel/******": "7.10.2"
很幸运,固定@babel/** 系列的版本之后能正常编译了,这个猜想正确了。
解决问题
既然知道原因了,那么解决办法也就有了 直接修改babel相关所有依赖包版本、或者加入package-lock.json? 可以解决,但是经过仔细考虑,最终还是放弃了上面的办法。 原因是:似乎上面的代码并没有什么问题,但是确实又在构建引入 SetArray 模块的时候报错了。 那么会不会是构建的问题呢?构建不支持这个 .mjs 后缀的文件?
经过搜索,网上最近也有很多人遇到这个问题,其中一个解决办法让我似乎明白了问题原因了
代码语言:javascript复制const config = {
module: {
// ...
rules: [
// ...
{
include: /node_modules/,
test: /.mjs$/,
type: 'javascript/auto'
}]
}
}
将上面的配置配置之后,果然不再报错了。
搜了下 javascript/auto
找到如下结果
这个图上说的应该就是原因了,虽然他说的是json文件,但是对于mjs应该也是同样的道理。
至此,问题解决,核心关键就在于配置mjs文件的构建 rule 类型为 javascript/auto
。
.mjs 是 nodejs 能识别的文件后缀,直接构建到项目中在前端浏览器是不能直接跑的,因此需要打包转义。