AMD named define works strangely
See original GitHub issueIntro
Hi guys! We have a huge microfront SPA with hundreds of scripts. There is a custom loading system and it uses fetch + eval. And now we want to migrate to SystemJS with AMD for backward compatibility. I’ve tried following scenario:
- Loading each microservice with System.import().
- Using
define(['sharedDep1'], function(sharedDep1){})
inside js files - And using
define('sharedDep1', function(){})
for shared dependencies in a core script.
And then I got a very strange bug. Sometimes some of modules export a wrong value, as if the different modules are messed up. Something like that:
System.import('moduleA').then(console.log) // And there is a moduleB in the console
After some investigation I figured out that it’s because of a race condition. So it’s very hard to reproduce and I’ve got it just because I have a huge SPA. Here’s what’s happening:
System.import()
adds a script into the document- It sets onload event listener that will call
getRegister
after loading - Another script finished its loading and that caused my code with amd
define
to be called define
is working synchronous, it sets firstName and firstNamedDefine- It sets
setTimeout
that clear them in the end - Previous script is loaded and it fires onload event, then
getRegister
will be called andif (firstName && url) {
is true
After that for some reason systemjs will use one module instead of the other. I think the problem in this PR #2352 I guess there is a race condition between eventloop macrotasks: setTimeout and onload event.
Demonstration
Because of the race condition it’s hard to reproduce apart of our code. So I wrote a synthetic example with multiple fake requests. I made a loop with random choice of import or define. Check it out: Code Sandbox: https://codesandbox.io/s/modest-chandrasekhar-lb7z6?file=/index.html
Expected Behavior
define
call doesn’t affect on System.import()
Every import returns its own module.
In my example it will be message We couldn't find the bug
in the console
Actual Behavior
If we call define
at the wrong moment, some modules will be mixed up.
In my example it will be message expect module b: {a: "a"} We've finally found the bug!
in the console
Issue Analytics
- State:
- Created 2 years ago
- Comments:11
Fix released in https://github.com/systemjs/systemjs/releases/tag/6.11.0
Or can we use tha sandbox example somehow?
And I’ve noticed that there is no need for
Promise.resolve
arounddefine
in my sandbox. Just a “synchronous”define
insidesetInterval
is enough. https://codesandbox.io/s/keen-firefly-0bomu