-
Notifications
You must be signed in to change notification settings - Fork 949
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
Build CommonJS module along with ESM and IIFE #1655
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is right but I wonder if we should be providing a "module" here as well (see https://webpack.js.org/guides/package-exports/#providing-commonjs-and-esm-version-stateless)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I was thinking the same thing, although I'm not sure whether the
"exports"
key has priority over the top-level"module"
key or not. I've not seen anything stating which to use, just the"export"
is more flexible.TL;DR, it sounds like adding the
"exports"
top-level along with a"type": "module"
is the typical way to support ES modules, and the top-level"module"
key I added might not be necessary if we add the"type"
key instead.(notes from my reading and digging into the Yarn 2 PnP docs and source)
Okay, if I understand my initial reading on this it sounds like node will treat
.cjs
and.mjs
different when callingimport
, and.mjs
can't berequire
'd. Setting the extension to.mjs
will tell node and modern browsers how to treat it, but then you have to deal with people running into issues where they're doing early development without a bundler and have web server config to only allow js, css, and jpeg, or similar issues that we wouldn't want to force on new folks just trying to get started"type": "module"
sounds like it is the implicit way to do it, and it gives a hint to node/bundlers to treat the import ending in.js
as an ES module (i.e. as a.mjs
), while still allowing flexibility.This makes sense to me why we're doing it this way 🤯
This set of articles seems to summarize rather well:
https://dev.to/bnb/conditional-exports-supporting-both-import-and-require-3ihg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so my take-away from all of that is that the configuration in this PR is seemingly correct.
@mveytsman possibly, but i am hesitant to make further changes :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw thanks @felix-starman for the thorough reply!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to be clear, we are saying that an alternate version of this change (for the relevant) might look like so:
is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so?
I did some testing and at least for my purposes, esbuild likes to default to using the "iife" (immediately invoked function expression) format, and wraps the
cjs
file so it can do an "import" at runtime. I was only able to force esbuild to use theesm.js
by setting it as the"main"
, which is an oddesbuild
thing? (evanw/esbuild#840)Ultimately though, having the
"module"
at the top level looks like it is potentially helpful in certain scenarios?The
"main": "...cjs.js"
works for Yarn2 + esbuild when following the docs, and assuming there is a way to tell esbuild to prefer theesm.js
file over thecjs
, it worked just fine then too.From the general gist, it seems like leaving the "module" and just adding the "type" is just fine too?
I thoroughly dislike JS dependency resolution now 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Welcome to the party @felix-starman :) and thank you again for the very thorough response!
I've been reading through the links you shared, as well, as the changelog for esbuild, just to get a better sense of things. I think I have that now, so I will share what I have found :)
After digging through the esbuild changelog entries, most notably those in 0.7.0 and 0.10.0, I finally landed on the esbuild docs for main fields which has the most succinct explanation I have yet seen. I will summarize here:
package.json
–"main"
- This is for node, so it's expected to be CommonJS (CJS)."module"
- This is for ECMAScript modules (ESM), except node uses "type": "module" instead. Also lots of packages incorrectly use module to mean, "code for the browser"."browser"
- "allows bundlers to replace node-specific files or modules with their browser-friendly versions." I think this has not yet been proposed for Phoenix packages, but perhaps it should be? 🤔defaults–
"The default main fields depend on the current platform setting and are essentially
browser,module,main
for the browser andmain,module
for node. These defaults should be the most widely compatible with the existing package ecosystem. But you can customize them like this if you want to:"esbuild app.js --bundle --main-fields=module,main
There is so much nuance here. My understanding is that specifying "exports" runs the risk of someone loading both the ESM and CJS bundles into their code, but esbuild does its best to mitigate that? I also get the impression esbuild ignores "exports" entirely, but I am sure other bundlers will rely on it.
My final takeaways:
--main-fields
flag if they need to change the default"exports"
with the top-level"browser"
key, but given multiple reports of these settings working for people, I think we save that for another day :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am leaving this unresolved for posterity :)