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:

  1. yarn build
  2. 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)

Most upvoted comments

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 feedback

There 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. the Empty 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 a ReferenceError.

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 problem

Yes, 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.