Webpack 导入返回未定义的,具体取决于导入的顺序

我正在使用 webpack + babel,我有三个模块看起来像这样:

// A.js


// some other imports here
console.log('A');
export default 'some-const';


// B.js


import someConst from './A';
console.log('B', someConst);
export default 'something-else';


// main.js


import someConst from './A';
import somethingElse from './B';
console.log('main', someConst);

执行 main.js时,我看到以下内容:

B undefined
A
main some-const

如果我在 main.js中交换进口,B成为第一个,我得到:

A
B some-const
main some-const

为什么 B.js在第一个版本中得到的是 undefined而不是模块? 出了什么问题?

33829 次浏览

After almost a full workday of narrowing down the issue (AKA hair-pulling), I've finally came to realize that I have a circular dependency.

Where it says // some other imports here, A imports another module C, which, in turn, imports B. A gets imported first in main.js, so B ends up being the last link in the "circle", and Webpack (or any CommonJS-like environment, for that matter, like Node) just short-circuits it by returning A's module.exports, which is still undefined. Eventually, it becomes equal to A0, but the synchronous code in B ends up dealing with undefined instead.

Eliminating the circular dependency, by moving out the code that C depends on out of B, has resolved the issue. Wish Webpack would somehow warn me about this.

Edit: On the last note, as pointed out by @cookie, there's a plugin for circular dependency detection, if you'd like to avoid hitting this problem [again].

This plugin(pointed above) solved the issue for me as well.

I recommend setting this flag to avoid adding additional circular dependencies in the future.

// add errors to webpack instead of warnings
failOnError: true

There is also a eslint plugin to address it.

In my case problem was solved by changing output libraryTarget to commonjs2 in the webpack config:

  output: {
path: `${__dirname}/dist`,
filename: '[name].js',
libraryTarget: 'commonjs2',
},