question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Circular dependencies not working as with ES modules

See original GitHub issue

Demonstration

Reproducing this bug has been a bit tricky so I created a repository: https://github.com/isidrok/system-circular-dependencies-bug (Sorry for the size of the reproduction but I don’t know how to generate proper System code without Rollup).

The folders ‘system’ and ‘es’ contain the chunks generated by Rollup in its respective formats. As you can see, there is a circular dependency between ‘b.js’ and ‘c.js’.

Launching an http server (npm start) and loading both pages (http://localhost:8080/system.html and http://localhost:8080/es.html) shows that the same code loads as ES format but fails as System.

If we eliminate the circular reference caused by the file ‘0\commonjsHelpers.js’ generated by @rollup/plugin-commonjs (nothing to do with this issue, just for the reproduction) by uncommenting line 17 of ‘rollup.config.js’ and building the app again (npm run build) then both pages load without errors since there are no circular references.

Expected Behavior

Modules with circular references can be executed as its done using ES modules.

Actual Behavior

Modules with circular references fail to execute.

Edit: simplify reproduction

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
guybedfordcommented, Sep 30, 2020

@isidrok RollupJS System output does not support circular references and I don’t think it should. The argument for this is that chunk circular references always need to load together, so you should just make them the same chunk. There’s no real practical reason to separate chunks across circular reference boundaries.

Perhaps we could make a warning in this case.

1reaction
joeldenningcommented, Sep 30, 2020

Hi @isidrok, thanks for the clear description and repository demonstrating the issue.

The issue here is related to rollup, not to SystemJS. Here is the error in the browser console for the systemjs page:

image

The way that rollup plugin commonjs is using the createCommonjsModule function is by injecting it into c.js and then importing it from c into b.js.

Regarding circular dependencies, the ES module spec first “links” the “hoisted exports” and then “instantiates” each module sequentially. The linking phase sets up the bindings for the exports and is what allows for the createCommonjsModule function to be available inside of b.js even before c.js has fully instantiated. All hoisted exports are available during initial execution of circular dependencies, but other exports are not.

SystemJS supports “hoisted exports during the link phase” with the following syntax:

System.register([], (_export) => {
  // link phase
  // All hoisted exports go here
  _export('foo', 'the hoisted export!');

  return {
    execute() {
      // instantiate phase
      _export('boo', 'other thing');
    }
  }
})

When rollup compiles to System.register format, it never does hoisted exports. You can see that this is the case by looking at this line: https://github.com/isidrok/system-circular-dependencies-bug/blob/b6e8ff9c7c4c1eddefa44d2aebc6987bd584bc03/system/c.js#L10.

To solve it, there are two options:

Solution 1

Don’t rely on hoisted exports / linking phase. To do this, you can remove the commonjs rollup plugin.

Example: https://github.com/isidrok/system-circular-dependencies-bug/pull/1

Solution 2

Make the createCommonjsModule function a hoisted export.

Example: https://github.com/isidrok/system-circular-dependencies-bug/pull/2

I think that this solution is the ideal one, but it requires changes to rollup / rollup-plugin-commonjs. It might be best to open an issue up with rollup to look into it. If you do so, feel free to mention me in the rollup issue and I can help explain what needs to change.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ES6 Modules and Circular Dependency - Stack Overflow
So you break the circle between X and Y , and you will need to start the import chain at Y - it...
Read more >
How to Analyze Circular Dependencies in ES6? - Railsware
ES6 Circular dependencies. In ES6 modules can have a single default export as well as many more granular named ones. Each module can...
Read more >
How to solve this basic ES6-module circular dependency ...
How to solve this basic ES6-module circular dependency problem? · Create the conceptual function "scope", which exists immediately as soon as the function...
Read more >
How to fix nasty circular dependency issues once and for all in ...
The case. The module loading order in JavaScript is deterministic. Yet it is not very easy to follow in large projects. The reason...
Read more >
How to Eliminate Circular Dependencies from Your JavaScript ...
Circular dependencies are usually an indication of bad code design, and they should be refactored and removed if at all possible.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found