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

How to control which distribution of a dependency gets used #102

Closed
tomwayson opened this issue Aug 15, 2018 · 8 comments
Closed

How to control which distribution of a dependency gets used #102

tomwayson opened this issue Aug 15, 2018 · 8 comments

Comments

@tomwayson
Copy link

My addon depends on a library that is distributed as CJS, ESM, and UMD, as the package main, module, and browser fields respectively.

I'm still learning how ember-auto-import works, but what I think I want is have it import the ESM files so that webpack can tree shake them as they get brought into the app, right?

However, it appears that what is being brought in is the UMD files, I'm guessing b/c this line gives preference to the browser field:

https://github.com/ef4/ember-auto-import/blob/0dadde0de99a107bc51f26304c504cc3b91ffe46/ts/splitter.ts#L18

Is there a way to give preference to the module field so that ESM files will be used instead?

@ef4
Copy link
Collaborator

ef4 commented Aug 17, 2018

It's hard to guess the best default here that works for everyone. And while we could make it configurable, the problem is that it takes effect globally. Apps and addons all need to agree, or they will break each other's dependencies.

(Lots of things about webpack config are not composable, in the sense that separate packages cannot have their own opinions about their own dependencies.)

There is a workaround you can use for your specific case. You can set an alias for the particular library you use that picks the exact entrypoint you really want:

// In your ember-cli-build.js file
let app = new EmberApp(defaults, {
  autoImport: {
    alias: {
      'the-library': 'the-library/path/to/modules/entrypoint'
    }
  }
});

The downside of this is that it effectively hard codes the current value of the library's module field in your own config, so if they change that in the future you would also need to change your alias to follow it. I supposed we could mitigate that downside by adding an option to alias indirectly via a field in the library's package.json.

@tomwayson
Copy link
Author

tomwayson commented Aug 17, 2018

Thanks! That seems like a perfectly reasonable workaround.

I supposed we could mitigate that downside by adding an option to alias indirectly via a field in the library's package.json

I think that would be useful. I think you could get away w/ using 'the-library': <'module'|'browser'|'main'|'the-library/path/to/custom/entrypoint'> since the module, browser, or main keywords shouldn't be valid custom paths, so if any of those strings are passed in, then it should fetch the value of the corresponding field from package.json.

@simonihmig
Copy link
Contributor

Apps and addons all need to agree, or they will break each other's dependencies

@ef4 could you explain what kind of breakage can be expected, e.g. when importing an ESM build instead of UMD?

This turns out to be a bit annoying as I believe most users expect that ember-auto-import will tree-shake all their imported dependencies out of the box, which it will not apparently, if the library ships with a browser build.

Also for addons that depend on ember-auto-import and some huge, but nicely tree-shakable library they will have to explain their users to manually add that ember-cli-build.js config to their apps, which is annoying and can be easily forgotten. So when they don't invest the time into bundle analyzing / perf budget limits etc. they will easily ship a huge bundle without even noticing.

@ef4
Copy link
Collaborator

ef4 commented Jan 24, 2020

If the library ships with a browser build, that's a pretty clear decision from the library author about how they think their library should be used in browsers. Prioritizing module higher is very likely to break libraries that would have worked if we prioritized browser.

Also, we currently follow the webpack defaults. Since webpack is so popular, I think library authors are more likely to test their library with the webpack defaults than with any alternative config.

I hear what you're saying, but we're really just stuck here with the state of the art of NPM package metadata.

@ef4
Copy link
Collaborator

ef4 commented Jan 24, 2020

could you explain what kind of breakage can be expected, e.g. when importing an ESM build instead of UMD?

The problem is that people use browser vs module for more than just that. They use browser specifically to ship an implementation that works in browser, while the rest of their library is intended to work only in node.

@simonihmig
Copy link
Contributor

They use browser specifically to ship an implementation that works in browser, while the rest of their library is intended to work only in node.

Got it, yeah, that would be bad! 😩

Unfortunately then a lot of library (and library boilerplates) come with a rollup/etc. config that does this, even when they are browser-only or "isomorphic":

  • browser: UMD
  • main: CJS
  • module: ESM

@tomwayson
Copy link
Author

You had me at

we currently follow the webpack defaults

FWIW - I think you should keep doing that.

:)

@NullVoxPopuli
Copy link
Contributor

There is some good discussion here, and looks like all questions are resolved! 🎉 if that happens to not be the case, please feel free to open a new issue with more questions 🥳

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

No branches or pull requests

4 participants