-
Notifications
You must be signed in to change notification settings - Fork 3k
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
refactor: node native esm #6043
Conversation
Thanks for tackling this - we have few internal attempt and failed to make things work to satisfy for some conditions. Please ensure this should pass at least
|
I'm marking as blocked for now since this is in-progress. |
FWIW, my understanding is that this is the correct and recommended approach as far as TypeScript is concerned. |
Back in the days I recall there's some problem around intellisense or other ts service things, is it now working? |
TBH, I'd be hesitant to say that the entire TS ecosystem will be working with it, despite it being the recommended approach. I'll have a look at my notes, this evening, for some links to 'official' TS statements. At work, ATM, hence the non-cartant GitHub account. |
I peeked few ts issues back in time and afaik official recommendation is bit behind of supporting things. (we have to double confirm but) if recommended change requires some churns around navigating code, or intellisense or vice versa I'd say it's not something we can easily adapt. |
mind elaborate this? we have single package.json for published pkg (i.e https://unpkg.com/browse/rxjs@7.0.0-beta.9/package.json) and don't have per-dist specific. |
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 would like to recommend to split commits between other changes to appending .js
extensions, otherwise reviewers are not possible to go through changes easily.
The top level package is Otherwise it will revert to exports[*].require, (or main and aliases folder structure if sufficiently old). |
oh, I mean node.js docs / spec reference I can read about. |
This is a good place to start https://nodejs.org/dist/latest-v15.x/docs/api/packages.html#packages_modules_packages |
I am aware of those docs. I think I missed part you specifically mentioned about cjs interop and would like to read those part. |
Gotcha, Maybe this: (I'm using conditional exports to support dual mode) https://nodejs.org/dist/latest-v15.x/docs/api/packages.html#packages_dual_commonjs_es_module_packages |
6487900
to
a03b39b
Compare
Regarding the |
2249a9d
to
5a41e95
Compare
Split commits added! This is ready for review. |
integration/import/package.json
Outdated
@@ -0,0 +1,11 @@ | |||
{ |
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.
where's package.json for esm?
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 forcing esm with the .mjs
extension in these tests.
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 I'm bit confused. Purpose of this integration test is trying to mimc actual user's package.json with various config, so we can't enforce something since we can't ask user to adjust package.json. That's reason there was cjs/package.json
, and I expect esm have same package.json have type:module
to test esm import when user decides to go with native esm. So in total, we expect at least 3 tests - cjs
without any type
(for node.js doesn't support type
property) / cjs
with type:cjs
/ esm with type:module
.
User can choose either use mjs, or decide type:module
and treat all js as esm.
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.
Mind elaborate how current test covers above cases?
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.
My thought was that by invoking cjs and mjs explicitly with file extensions, I'm exacting the codepaths in node that load the code with the correct loader. Whether that loader option is invoked via a package.json or a type field is a node implementation detail that may expand in the future. IMHO adding a separate package.json is just another way node gives you to choose a loader, but I don't think it needs to be a focus of these tests.
Right now the assertions being made are ensuring that the module exports are equivalent when run via cjs and esm.
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.
IMHO adding a separate package.json is just another way node gives you to chose a loader but I don't think it needs to be a focus of these tests.
as long as your test can represent real user's package.json usecase to test, it should be ok. But I'm bit hard to understand if it's covered. So current way can we verify flows like below?
- user uses old / latest node.js, package.json doesn't have type field and want to use cjs
- user uses latest node.js, package.json have type field to cjs, want to use cjs
- user uses latest node.js package.json have type field to esm, want to use esm
- (need to be added) webpack / other bundler picks up esm correctly
Whether that loader option is invoked via a package.json or a type field is a node implementation detail that may expand in the future
This isn't about node.js internal, As stated this test try to mimic current real world package.json structures as user load their module in various different way. Regardless of how node.js treats, we should support existing ergonomics user uses.
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.
For sure, For the flows you outlined - the answers are declared in the package.json
main
field is discovered ->dist/cjs
is loaded (node 11 in the tests is doing this)exports
field is discovered -> import ? ->dist/esm
:dist/cjs
(node 12+) Edit: - added node 13 array fallbacks to cjs for early 13 versions- same as 2
- Webpack implements resolution logic based on these fields as well
I don't know if there is value to adding more tests here since the added test now validates that both esm and cjs can be requested and contain a consistent API.
integration/import/esm.mjs
Outdated
import { join, dirname } from 'path' | ||
import { fileURLToPath } from 'url' | ||
import * as rx from 'rxjs' | ||
import * as operators from 'rxjs/operators' |
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 is highlighting the new feature that is added in this PR -- currently these lines of code are not possible in 7.0.0-beta.10
2438646
to
b7d2fdd
Compare
a009bf9
to
263dfca
Compare
Core Team Meeting Notes: We've decided we want to do this at some point, but version 7 isn't the right time to do so. We'd like to let this ecosystem simmer for a bit and address this maybe in version 8. |
Closing for now then, thanks for the update |
Description:
This PR changes the package to a
"type": "module"
package. Adding anexports
entry to the package.json which going forward will do the work of the generate-alias helperRelated issue (if exists):
#6030 #4416 #2858 #3858
General beginning for deno support via compatibility layer #5350 #5486
Breaking Changes
When a user is on node > 12.7 They will no longer be able to use deep import paths, and can only use what is specified in
package.json#exports
.require('rxjs/dist/cjs')
Node will throwa
ERR_PACKAGE_PATH_NOT_EXPORTED
error.A user on early EOLd node 13 usingnode 13 compat dropped in Add exports within package.json to enable scoped package loading. #6192--experimental-modules
will be importing a commonjs module as esm since conditional entries are not supported.