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

require.js added to global namespace, when serving via dartdevc #33979

Open
yury-yufimov opened this issue Jul 25, 2018 · 30 comments
Open

require.js added to global namespace, when serving via dartdevc #33979

yury-yufimov opened this issue Jul 25, 2018 · 30 comments
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. dev-compiler-build web-dev-compiler

Comments

@yury-yufimov
Copy link

This is one for discussion, I think.

While migrating to Dart2.0 (2.0.0-dev.67.0), we faced following issue:
DDC adds <script defer="" src="/packages/$sdk/dev_compiler/amd/require.js"></script> to page, which defines global functions require and define.
That fact affects some third-party libraries, that are also imported to project.
If such library sees global define function, it defines new module, otherwise - set global variable.
Problem is, we don't use requirejs in production environment.
Of course, we can add condition: load library via requirejs in dev-environment, by script adding - in prod one.
But I think, that can be a common problem for large products.

Another possible solution: move ddc's requirejs to some namespace...

@matanlurey
Copy link
Contributor

/cc @natebosch and @jakemac53 if this should be a build issue instead.

@natebosch
Copy link
Member

natebosch commented Jul 25, 2018

I think DDC is the right place to track this for now. I know DDC supports other strategies than require.js and switching to one of those would be a build issue, so if we decide that's the right course of action we can move the issue over.

@matanlurey
Copy link
Contributor

Thanks Nate!

@Anrock
Copy link

Anrock commented Aug 28, 2018

I've got similar case. My Electron app loads dart webapp written in dart with node integration enabled to enable intercommunication between dart and electron apps. Obviously Node require which is defined even before page starts loading conflicts with DDCs require.

@natebosch can you elaborate more on "other strategies than require.js"? Are they user-configurable?

@natebosch
Copy link
Member

As of today, no, using anything other than require.js is not an option with build_web_compilers.

The dartdevc compiler does support using other strategies, but using them would require either a lot of manual work to configure how to invoke the compiler for your project, or a lot of work to integrate it with a build system to do it automatically. If we want to support other strategies we'd most likely need to do it in build_web_compilers

@jodinathan
Copy link

I wanted to lazily load third-party libs but most of them uses requirejs and didn't work because of this.
Now I found a way that is removing the window.define after Dart loads

https://stackoverflow.com/questions/55113108/is-it-possible-to-lazily-use-js-libs-with-dart/55192098#55192098

@jakemac53
Copy link
Contributor

@jmesserly wdyt about adding some optional argument which is a global namespace to look for require/define in? Essentially we could pass in --require-namespace or something (there is probably a better name for it) and it would just prepend that in front of all require/define calls?

@jakemac53
Copy link
Contributor

There is also this FAQ https://requirejs.org/docs/faq-advanced.html#rename which says not to do this explicitly though, but the reasoning may not apply in our case.

@jmesserly
Copy link

wdyt about adding some optional argument which is a global namespace to look for require/define in? Essentially we could pass in --require-namespace or something (there is probably a better name for it) and it would just prepend that in front of all require/define calls?

That sounds quite reasonable to me.

@yury-yufimov
Copy link
Author

@jakemac53 , I'd like to add couple of examples. As you can see in
https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.45.0/codemirror.js
https://cdnjs.cloudflare.com/ajax/libs/jquery-migrate/3.0.1/jquery-migrate.js
https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.1/handlebars.min.js
It's quite common for JS-libraries to start package with code like

if ( typeof define === "function" && define.amd ) {
    define(factory);
} else {
  window.MyModuleClass = factory();
}

This means, that right now we need to use this libraries differently in production (with no defined window.define method), and in developer environment (with requirejs from ddc, which defines window.define method).

@vsmenon vsmenon added this to the D24 Release milestone Apr 24, 2019
@vsmenon vsmenon removed P1 A high priority bug; for example, a single project is unusable or has many test failures labels May 17, 2019
@vsmenon vsmenon removed this from the D24 Release milestone May 17, 2019
@xylobol
Copy link

xylobol commented May 17, 2019

@jmesserly wdyt about adding some optional argument which is a global namespace to look for require/define in? Essentially we could pass in --require-namespace or something (there is probably a better name for it) and it would just prepend that in front of all require/define calls?

This seems like a good solution. What also might make sense is "scoping" requirejs where only DDC-compiled programs can access it.

@vsmenon vsmenon added the area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. label Jul 20, 2019
@harryterkelsen
Copy link
Contributor

I'm hitting this issue while trying to dynamically load firebase-app.js in DDC

@deakjahn
Copy link

deakjahn commented May 15, 2020

I would be one of the users that would argue for it or something equivalent (see the issue referenced above). Now that Flutter Web is here and plugins are getting web support, many of those would need to load their related JS libraries. The fact that it is readily available in debug mode (visible in Chrome console among the sources) makes us believe that this is something intentional and also that being stripped in release mode is just a bug.

If you decide on another loader, no problem, as long as it's compatible with the usual library formats like UMD and others. But don't remove or hide that capability on purpose now that Flutter Web is finally a reality.

@natebosch
Copy link
Member

something intentional and also that being stripped in release mode is just a bug.

It is not intentional and we don't plan on add any module loader on production mode. Trying to fit into other modular JS apps is non-goal. Our most likely resolution will be to stop using require.js at all, even in dev mode.

@jakemac53
Copy link
Contributor

jakemac53 commented May 15, 2020

Note that using a format which is compatible with typical module formats is also a non-goal at this time. We just happened to use one because it was well defined and easy to use.

However, we have already hit several limitations and its likely we will do something custom in the future that allows for a better dev experience, such as reloading individual modules in the heirarchy without reloading all parents of that module.

@deakjahn
Copy link

deakjahn commented Jun 1, 2020

With CanvaskKit, there is an even bigger problem:

Uncaught Error: Mismatched anonymous define() module: function() { return CanvasKitInit; }

This practically makes it impossible to use a require.js brought along with our own code to be used for our own purposes. Well, I hope not completely impossible but I'm still struggling to find a way...

@Ehesp
Copy link

Ehesp commented Sep 2, 2020

Just chiming in on this one - this impacts FlutterFire development as we're unable to directly pull in the Firebase SDK programatically, instead they have to be loaded via the CDN within the <head> section.

@deakjahn
Copy link

deakjahn commented Sep 2, 2020

@Ehesp As mentioned in flutter/flutter#58428, all it would take is to add a single module ID to the JS. I haven't been able to even trigger a response so far. :-)

@annagrin
Copy link
Contributor

annagrin commented Dec 5, 2022

@ditman Run into this issue while reviewing our issues with most comments. Is it still relevant for flutter to fix? If yes, what is is the priority here?

@ditman
Copy link
Member

ditman commented Dec 5, 2022

@annagrin yes, I think this is still relevant.

In addition to the stuff mentioned above, requireJS does not support TrustedTypes (and probably will never do), so Flutter can't use TrustedTypes in development mode.

I'm not sure about the priority of this, and I am also not sure of the ownership (it's probably shared :P). I know flutter configures requireJS here, but I think DDC is generating the requireJS modules when compiling in debug mode?

IMO, we should just stop using requireJS and switch the DDC output to standard ES Module import/export, but I'm not sure how breaking that is (probably quite a bit). (keep reading to see why this is A Bad Idea™)

@jakemac53
Copy link
Contributor

Fwiw, I don't know how much flutter uses it, but in build_web_compilers we do use a fair number of features from require.js that would not be available with standard ES6 modules. We can intercept errors for failed modules, as well as modify the paths for where to actually look up modules, customize timeouts, etc.

Doesn't mean we couldn't migrate to ES6 modules though, but it would be a fair bit of work and we would lose a few nice to have features.

@ditman
Copy link
Member

ditman commented Dec 5, 2022

Ah, thanks for the extra context @jakemac53; the only thing I see from the Flutter side is the module loading AFAIK.

@jakemac53
Copy link
Contributor

jakemac53 commented Dec 5, 2022

Oh another topic for this is hot reload/restart. I don't know if you can achieve that with es6 modules... past support always used custom require.js hooks to reload specific modules, or similar support in our custom module loader.

@ditman
Copy link
Member

ditman commented Dec 5, 2022

require.js is EoL'd, but not even the maintainer knows what to recommend in its place.

@natebosch
Copy link
Member

have we ever sketched out how much effort it would take to migrate to the internal module strategy in build_web_compilers? Would it require SDK changes?

@jakemac53
Copy link
Contributor

have we ever sketched out how much effort it would take to migrate to the internal module strategy in build_web_compilers? Would it require SDK changes?

I think it would be a fair chunk of work, plus rolling it out may be challenging because there may be assumptions in webdev and/or dwds that would have to be resolved.

@jakemac53
Copy link
Contributor

Fwiw, instead of changing build_web_compilers I would probably just jump straight to using frontend_server.

@annagrin
Copy link
Contributor

Related: #52361

@ditman
Copy link
Member

ditman commented May 12, 2023

One more: flutter/flutter#126131

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. dev-compiler-build web-dev-compiler
Projects
None yet
Development

No branches or pull requests