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.

AMD named define works strangely

See original GitHub issue

Intro

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:

  1. System.import()  adds a script into the document
  2. It sets onload event listener that will call getRegister after loading
  3. Another script finished its loading and that caused my code with amd define to be called
  4. define is working synchronous, it sets firstName and firstNamedDefine
  5. It sets setTimeout that clear them in the end
  6. Previous script is loaded and it fires onload event, then getRegister will be called and if (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:closed
  • Created 2 years ago
  • Comments:11

github_iconTop GitHub Comments

1reaction
joeldenningcommented, Oct 18, 2021
0reactions
bmpolonskycommented, Oct 18, 2021

Or can we use tha sandbox example somehow?

And I’ve noticed that there is no need for Promise.resolve around define in my sandbox. Just a “synchronous” define inside setInterval is enough. https://codesandbox.io/s/keen-firefly-0bomu

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to load multiple named AMD modules defined in a single ...
Loading a module that calls define through a <script> tag is ... some really strange cases where to get incompatible assets to work...
Read more >
Why AMD? - RequireJS
This page talks about the design forces and use of the Asynchronous Module Definition (AMD) API for JavaScript modules, the module API supported...
Read more >
How many of you think AMD GPU naming scheme is a mess?
The naming still clearly represents the "power", with bigger numbers meaning faster CPU. The same can't be said for their GPUs, where the...
Read more >
Solved: Default Radeon WattMan settings has been restored
I have stumbled by accident on a strange workaround that I would like to share with others so they can try and confirm...
Read more >
Understanding AMD Processor Names
This reminds me of when Microsoft had their ill-fated penchant for using R2 in their product names, such as SQL Server 2008 R2....
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