webpack: ReferenceError: Cannot access '' before initialization
Bug report
What is the current behavior?
I am not quite sure how to describe what the situation actually is, but the bottom line is that in some rare cases importing a module in the wrong order causes ReferenceError: Cannot access '<something>' before initialization
.
Enabling both innerGraph
and usedExports
seems to allow one to work around the problem.
If the current behavior is a bug, please provide the steps to reproduce.
See the reproduction repository: https://github.com/wesselvdv/used-before-initialization
Reproduction steps:
- yarn build
- node dist/index
What is the expected behavior?
That importing in whatever order always works regardless of optimization strategies enabled or disabled.
Other relevant information: webpack version: 5.23.0 Node.js version: 14.10.1 Operating System: Arch Linux Additional tools:
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 20
- Comments: 16 (7 by maintainers)
Much like a circular dependency
I have it scoped down to the module flag in TS, if the
tsconfig.json
specify"module": "commonjs"
the bug reproduces, if instead it is set to"module": "es6"
it does not@alexander-akait the issue doesn’t present when optimizations are present and also doesn’t reproduce without the usage of webpack looks more like a BUG
Yep,
Circular Dependency
is the problem sometimes,Circular Dependency Plugin
should solve the problem, maybe we move it in core in future, we have the issue https://github.com/webpack/webpack/issues/7962, nothing to fix on webpack side here for original issue, sorry, feel free to feedbackThere is a circular dependency in
@effect-ts/system
:@effect-ts/system/_traced/esm/Layer/definitions.js
exports LayerSuspend, but before it does that it will import@effect-ts/system/_traced/esm/Managed
, which imports@effect-ts/system/_traced/esm/Managed/methods/api.js
, which imports@effect-ts/system/_traced/esm/Layer/core.js
, which imports LayerSuspend from@effect-ts/system/_traced/esm/Layer/definitions.js
(which is not finished yet, as it’s circular) and uses LayerSuspend in initialization in this line:export const Empty = /*#__PURE__*/ new LayerSuspend(() => identity())
.Note that most of these modules are flagged as side effect free and there are also a few
/*#__PURE__*/
annotations, so a lot code might be dropped when optimizations are enabled, which could “fix” this code when e. g. theEmpty
export is unused.Also note that execution order might change in side effect free modules even in development mode (side effects optimization is also enable in dev mode), so you might get different behavior. There are cases where code with circular dependencies depends on a certain execution order to work properly. This kind of code has an implicit side effect of putting some modules into the module cache.
Also note that when transpiling code from ESM to CJS, it might look like that “fixes” some of the circular dependencies as exports in circular dependencies might return
undefined
instead of throwing aReferenceError
.Here is a simple example of this behavior: typescript playground. The typescript transpiled code logs undefined instead of throwing a ReferenceError.
@JustFly1984 You can try using this plugin to warn about circular imports
Because
ts
generate wrong code, but when we try to bundle we face this problemYes, I see, bug (I think)
I also ran into the “ReferenceError” because I had circular imports in my TypeScript code by using barrels. I am using barrels now only for exports and don’t use them myself in the library code that I write.
Using the “Circular Dependency Plugin” really helped to spot these problems. I also set “optimization.minimize” to “false” and “stats.errorDetails” to “true” in my webpack config, so that I can debug the non-minified code.
In my case it was circular dependency issue. Sadly typescript or eslint does not warn about circular imports.