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

Exporting as ES Module Syntax (ESM) #62

Closed
abdonrd opened this issue Sep 26, 2019 · 21 comments
Closed

Exporting as ES Module Syntax (ESM) #62

abdonrd opened this issue Sep 26, 2019 · 21 comments

Comments

@abdonrd
Copy link
Contributor

abdonrd commented Sep 26, 2019

Please, export "module" entry point in the package.json as ES Module Syntax (ESM).

More info about it here: https://www.pikapkg.com/about/

@zenparsing
Copy link
Owner

We added a module key in the past, but unfortunately this caused problems for some users.

#37

It seems that "fixing" things for one set of tools tends to break other tools. We also tried supporting .mjs for a while and that caused issues as well. Things may have changed in the ecosystem, though.

What is the practical benefit here? So that it can be indexed by pika?

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 4, 2019

With a proposal like this #64, the idea is to export the package in two formats:

  • Common.js format as lib/cjs/index.js (same as the current export)
  • ES Modules format as lib/index.js

The benefit is that importing the library becomes much easier in cases such as:

  • Load in the browser with any tool. All major browsers can load standard ES Modules now.
  • Load in bundlers like Rollup.

Many of the modern libraries are already exporting to ES Modules.

About the .mjs extension, was just a experimental proposal from Node.js.
But finally seems that the ES Modules implementation from Node.js will use just .js.

The link to Pika was just a reference to the ES module syntax.

@zenparsing
Copy link
Owner

Based on past experience, I'm still worried that supporting both module systems at the same time will cause issues for existing libraries. Can you give a concrete example of how not supporting both module systems is causing issues?

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 16, 2019

Try to use it directly in the browser, without tools. You can't use the standard ES Modules.

Example: https://glitch.com/edit/#!/cheddar-girdle

If you import the index.js you get an error:

Uncaught SyntaxError: The requested module 'https://unpkg.com/zen-observable/index.js' does not provide an export named 'default'

(I made the example work importing the src/Observable.js)

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 16, 2019

My final goal is use apollo-client directly in the browser as ES Modules. And apollo-client already export as ES Modules, but it has a couple of depedencies (zen-observable is one of them) that don't.

Then I get the error:

Uncaught SyntaxError: The requested module '...' does not provide an export named 'default'


Using the #64 PR, I have an app example using apollo-client directly in the browser; without any build or bundled step:
https://github.com/abdonrd/open-wc-application-apollo-client/compare/apollo-client-es-modules

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 16, 2019

Maybe the bad experience of the past was for not defining this in the package.json?

  "main": "lib/cjs/index.js",
  "module": "lib/index.js",

@zenparsing
Copy link
Owner

What is throwing this error:

Uncaught SyntaxError: The requested module '...' does not provide an export named 'default'

Is that rollup, or the browser, or something else?

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 16, 2019

This error is from the browser:

Uncaught SyntaxError: The requested module '../../zen-observable/index.js' does not provide an export named 'default'

Screenshot 2019-10-17 at 07 45 09

If you want to see it, just remove this line and run the application:

https://github.com/abdonrd/open-wc-application-apollo-client/compare/apollo-client-es-modules#diff-b9cfc7f2cdf78a7f4b91a753d10865a2R22

@zenparsing
Copy link
Owner

In order to use a library like apollo-client (that has dependencies) directly on the web, don't you need to either bundle up the dependencies or use an import map?

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 16, 2019

No, it is not necessary. You can test the application running without any build/bundled here:

https://github.com/abdonrd/open-wc-application-apollo-client/compare/apollo-client-es-modules

We only do the build & bundled step to optimize the application for production. But not during local
development. During local development the source code just works on the browser.

@zenparsing
Copy link
Owner

Sounds cool - I'll give it a try.

@abdonrd
Copy link
Contributor Author

abdonrd commented Oct 17, 2019

Great! Thank you @zenparsing!

@zenparsing
Copy link
Owner

This is a tough one. I tried to run the app but wasn't able to get it working (with the few minutes I had).

Node 13 will support ESM without a flag using "type": "module" in package.json, but it won't support dual-mode packages (where both ESM and CJS can be used for the same package at the same time). Given this direction, and the experiences I've had in the past with "module" and ".mjs", I'm still hesitant.

For now, I've added a better esm entry point at zen-observable/esm.js. For your use case, is there any way that you can tell the browser to look there for the package entry point?

@abdonrd
Copy link
Contributor Author

abdonrd commented Nov 3, 2019

As far as I know, the only way is to use the module/main fields, which is what tools usually understand as ES Modules. If you just add this to the package.json, what stops working?

  "main": "index.js",
  "module": "esm.js",

In the future, the idea is to use the exports field in the package.json.

@abdonrd
Copy link
Contributor Author

abdonrd commented Nov 4, 2019

And there are other big packages like Redux using this module/main fields:

https://github.com/reduxjs/redux/blob/c2973f480bc4e5b6bf7d42a714d4790311cd1a26/package.json#L26-L28

@semmel
Copy link

semmel commented Nov 10, 2019

@zenparsing Please push 0.8.15 on npm.
esm.js just solves my problem importing zen-observable! Thank you! 👍
UPDATE:
Actually never mind! I just changed my import statement from import * as Observable from 'zen-observable'; to import Observable from 'zen-observable';. Now it works with 0.8.14 as well.

@abdonrd
Copy link
Contributor Author

abdonrd commented Nov 19, 2019

There are any news @zenparsing? Thanks in advance!

@Splaktar
Copy link

Splaktar commented Jul 18, 2020

I am running into this same issue with an app built using apollo-client. It gives this error with Angular CLI version 10:

WARNING in /Users/splaktar/Git/my-app/node_modules/zen-observable-ts/lib/bundle.esm.js depends on 'zen-observable'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

https://angular.io/guide/build#configuring-commonjs-dependencies has some good links to explain why CommonJS modules don't support tree shaking and how ES Modules work.

zen-observable-ts is importing correctly:

import zenObservable from 'zen-observable';

But due to the lacking "module": "esm.js", that ends up getting the CommonJS module (index.js) instead of the ES Module.

It looks like the approach in PR #74 should solve this and hopefully avoid any of the pitfalls that were faced in the past.

@nikita-lobkov
Copy link

Any updates on this? Looks PR is still not merged yet :C

@bendehghan
Copy link

any update on this??

@zenparsing
Copy link
Owner

Will be addressed in #86

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