-
Notifications
You must be signed in to change notification settings - Fork 130
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
Adds es modules support and tests #126
Conversation
9b0e4ce
to
0ff4aef
Compare
…s' options in the package.json
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.
This looks great to me, the ESM wrapper sounds like a sensible approach as well.
@@ -0,0 +1,3 @@ | |||
{ | |||
"type": "module" | |||
} |
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.
This pattern definitely works if the .js
extension is important for both. I take it that is the constraint you're working too, even if .mjs
would be slightly simpler.
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.
Curious, what was the point of adding this almost empty package.json with no package name, no package version?
Sincerely,
ES Module Bundlers
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.
https://nodejs.org/api/packages.html#type
The "type" field defines the module format that Node.js uses for all .js files that have that package.json file as their nearest parent.
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.
Hmm, is it best to comprehensively interpret this spec like this though? To just drop a nested, nearly empty package.json
in a distribution directory, when thinking about all the nuances that go into an NPM package and bundling/transpiling packages?
And how is an NPM package like pkg-dir expected to behave now, in it's claim to:
Find the root directory of a Node.js project or npm package
The above pkg-dir
behavior will fail to resolve the root of the NPM package for tslib
after an ESM bundler follows to path ./imports/index.js
declared in package.json#exports['.'].imports
and then executes pkg-dir
with a cwd of: node_modules/tslib/imports/index.js
It seems the case that NOT using the .mjs
extension was a shortcut and may be more the problem here
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.
Hmm, is it best to comprehensively interpret this spec like this though?
The spec is quite intentionally written like this as far as I know. It intentionally doesn't use something like "package.json at the root of the package directory" multiple times
To just drop a nested, nearly empty package.json in a distribution directory, when thinking about all the nuances that go into an NPM package and bundling/transpiling packages?
Even before node has supported .mjs
, .cjs
, package.json#type
and more, it was already possible to define nested package.json
files. It was possible to put package.json#main
there to "redirect" the request to another location. I've been using this for years already.
And how is an NPM package like pkg-dir expected to behave now, in it's claim to:
I'm not sure if this package is implemented correctly but a lot of similar resolvers were implemented correctly in the past. All modern module bundlers etc already work just OK with those nested package.json
files. The rule, in fact, is quite simple if you want to just grab the root of a pkg, arguably you wouldn't even have to look for package.json
files but rather just find a directory nested directly within node_modules
directory
The tests seem like they will add some maintenance burden though - it does seem like overkill here to me. |
Co-authored-by: Guy Bedford <[email protected]>
I agree the tests are definitely overkill for this specific change. However, this entire lib has no tests and I'd rather make it easier for the next change like this 👍🏻 |
Co-authored-by: Guy Bedford <[email protected]>
"sideEffects": false | ||
"sideEffects": false, | ||
"exports": { | ||
".": { |
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.
Please provide "module"
condition as well. It's going to be supported by the upcoming webpack 5 and will allow it to keep only a single copy of tslib
in the bundle. Point of reference: https://gist.github.com/sokra/e032a0f17c1721c71cfced6f14516c62#reference-syntax
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'm open to covering this in a new PR, that gist isn't really enough docs for me to go with yet
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.
Sure, can be added afterwards.
There are no real docs for this yet on their page but this gist has been updated multiple times when they have been iterating over semantics. This is already implemented and shipped in webpack 5 RC.
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.
@Andarist do you have any examples of packages using the "module"
condition successfully for reference here?
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.
@guybedford I did not (mainly because conditional exports themselves are rather rare to find so far), but I've decided to showcase this using one of my smaller modules. Here are exports that I have defined:
https://github.com/Andarist/callbag-last-element/blob/07099fd55b4dfff80a7697065c71ce9b5fc07ade/package.json#L7-L14
and here is the webpack output:
https://github.com/Andarist/webpack-module-condition-test/tree/7bca3a5ae4f07b5429c7b36db3d43b2072b39cf2/src
Notice how last
function is only there a single time in this bundle even when mixing ESM and CJS files.
The input for this is as simple as:
// cjs-file.js
module.exports = require("callbag-last-element").default;
// index.js
import lastElement from "callbag-last-element";
import lastElementFromCjs from "./cjs-file";
console.log({ lastElement, lastElementFromCjs });
and can be found here (same repo)
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.
Thanks again to diving into this.
Please can we make sure to backport this to the 1.x branch as well as that still has significant usage for packages which assume ES module support in bundlers.
@@ -0,0 +1,7 @@ | |||
{ | |||
"type": "module", | |||
|
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.
Not required, but I'd be tempted to say you should move the "dependencies"
from https://github.com/microsoft/tslib/pull/126/files#diff-f1e4194bc14f4a4ca169da388d9135de to each individual test so they run in isolation.
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.
Aye, normally this is something I'd just throw into a yarn workspace and forget, but I'll make them all conform to a similar scripts structure then just loop through them
Co-authored-by: Ron Buckton <[email protected]>
3b12c15
to
964103a
Compare
9ff3943
to
2ee4347
Compare
Deprecates #121 #119 #87
This PR: