Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UMD support #453 breaks isolation and on websites that use require.js can cause script to crash #2451

Closed
danielbodart opened this issue Dec 22, 2018 · 9 comments
Labels

Comments

@danielbodart
Copy link

danielbodart commented Dec 22, 2018

🐛 bug report

(UMD support #453) breaks isolation by always trying to expose exports, this ideally should have to be turned on not done by default. However I understand this might be against the zero config / sensible defaults policy and also is a breaking change. In which case being able to turn this off would also work.

What is made worse is that when combined with require.js, depending how the script is loaded require.js will throw an error stopping the script from ever loading.

Basically require.js wants all scripts loaded after it has loaded to not be added to the page directly but done via require. If you call define (as any parcel built script will do automatically) anonymously then require will throw a "Mismatched anonymous define()" error.

This affects lots of different bundlers but unfortunately require.js will not relax this [constraint] (requirejs/requirejs#1763)

This might seem easy to fix, always load your script via require but if your script is loaded via tag managers or 3rd parties then this is impossible to handle.

I'm happy to try and create a pull request that supports disabling UMD if people agree with the problem!

🎛 Configuration (.babelrc, package.json, cli command)

parcel build anyfile.js

🤔 Expected Behavior

Would not expose modules via UMD (in prelude.js)

😯 Current Behavior

Breaks isolation by always exposing modules, causing a "Mismatched anonymous define()" error. if script is loaded any other way than via require

💁 Possible Solution

parcel build anyfile.js --no-umd

🔦 Context

We use parcel to build a standalone script that can be including on the page in many different ways by our clients or their clients.

@danielbodart
Copy link
Author

danielbodart commented Dec 22, 2018

Currently as a work around I'm hacking the generated javascript after I build it with parcel by disabling require.js support:

parcel build *.js
sed -ie 's/define.amd/define.XXX/g' dist/*.js

It's pretty flaky as if the logic/code changes in parcel this will break!

Edit: changed the replace to be 3 characters so source maps might still work!

@danielbodart danielbodart changed the title UMD support #453 breaks isolation on websites that use require.js UMD support #453 breaks isolation and on websites that use require.js can cause script to crash Dec 22, 2018
@adam1658
Copy link

adam1658 commented Feb 1, 2019

I'm having a similar issue. I'm building one script which gets injected into a number of different third-party systems we use. If any of those sites use UMD, parcel tries to register my entrypoint with it, which causes bugs in the host site.

My stop-gap solution is to add the following wrapper to generated bundles:

(function(){
    var define = undefined; // the UMD registration code won't find the global 'define' anymore!
    // generated content goes here
})()

I like @danielbodart's solution (a --no-umd flag), but a more flexible solution would be to allow providing a customised prelude, so we can omit the parts we don't like (prelude.js#L84-L103)

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.

@github-actions github-actions bot added the Stale Inactive issues label Jan 17, 2020
@github-actions github-actions bot closed this as completed Feb 2, 2020
@eduardomoroni
Copy link

eduardomoroni commented Jul 13, 2020

We're having the same error, this probably going to force us to move away from parcel. Could anybody from the core team chime in and give some insight?

I would be happy to work on the --no-umd if there's a endorsement from the lib maintainers.

@devongovett @mischnic @DeMoorJasper @wbinnssmith what do you think about this idea?

@github-actions github-actions bot removed the Stale Inactive issues label Jul 13, 2020
@lucastnr
Copy link

lucastnr commented Sep 29, 2020

I'm currently suffering of this same problem, the parcel is creating a anonymous define module, that conflicts with requirejs. The requirejs does not allow you to use a anonymous define at the same page it is installed.

There's a way to avoid that in the actual version of parcel?

@devongovett @mischnic @DeMoorJasper @wbinnssmith

@eduardomoroni
Copy link

@lucastnr I worked around this problem by adding a script to do as #2451 (comment) suggests.

(function (define) {
  var oldDefine;
  if (typeof define === 'function' && define.amd) {
    oldDefine = define;
    define = null;
  }
  
  // Your bundle goes here
  
  define = oldDefine;
})(window.define);

@vaporwavie
Copy link

vaporwavie commented Nov 19, 2020

Having a --no-umd option would be great! This has sincerely been a big headache during the past few weeks of development.

@danielbodart's suggestion does the job though. But of course it'd be amazing if we had a official way to do so.

@lucastnr
Copy link

Having a --no-umd option would be great! This has sincerely been a big headache during the past few weeks of development.

@danielbodart's suggestion does the job though. But of course it'd be amazing if we had a official way to do so.

Agreed!

@MRamonLeon
Copy link

MRamonLeon commented May 30, 2023

Same issue here because existing define method exist in the page (either requirejs or even requirejs/almond):

Basically require.js wants all scripts loaded after it has loaded to not be added to the page directly but done via require. If you call define (as any parcel built script will do automatically) anonymously then require will throw a "Mismatched anonymous define()" error.

Workarounded with:

<script src="remove-define.js" defer></script>
<script type="module" src="my-module.js"></script>
<script src="reintroduce-define.js defer></script>

Being remove-define.js:

window["define"] = window["__define"];
window["require"] = window["__require"];
window["__define"] = undefined;
window["__require"] = undefined;

And reintroduce-define.js:

window["__define"] = window["define"];
window["__require"] = window["require"];
window["define"] = undefined;
window["require"] = undefined;

Idea taken from: https://stackoverflow.com/questions/15371918/mismatched-anonymous-define-module/33635881#33635881

Be sure those scripts are sourced, not inline, to guarantee the order.

A better solution coming from the Parcel team would be appreciated. Just adjust the prelude.js change introduced here please: https://github.com/parcel-bundler/parcel/pull/453/files#diff-7eef34c10f39a3116be06b08acbbe73250a8af73bb540958c898c167ff97435cR89

Could you reopen this issue please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants