Open GeoffreyBooth opened 1 year ago
I’ll start: --experimental-type=module
/ --experimental-type=commonjs
.
--experimental-type
(--type
when stable) SGTM. It's close to <script type="module">
.
Maybe I missed some context somewhere, but why do we need another flag separate from --input-type
? Can we not just aim to switch the default of that one?
Maybe I missed some context somewhere, but why do we need another flag separate from
--input-type
? Can we not just aim to switch the default of that one?
Because that one only affects --eval
, --print
and STDIN, and I'm proposing having it affect many more things. It would be a breaking change if we expanded the behaviors of --input-type
.
Not clear why that would be considered a breaking change. If the flag was not supported in anything but those cases previously then this would just be a case of adding additional support, which sounds to me like a minor. 🤔
In any case, it sounds rather unfriendly from a usability perspective to have two different flags that sound like they do the same thing (Because they do! Just in slightly different contexts.) rather than sticking to the one flag we already have that does this. ESM is already confusing enough with all the extra configs and inconsistencies with CJS-derived expectations, we don't need proliferating flags adding to the complications. 😬
Not clear why that would be considered a breaking change.
Well, maybe it wouldn’t be. Currently if you run node --input-type=module test.mjs
it throws Error [ERR_INPUT_TYPE_NOT_ALLOWED]: --input-type can only be used with string input via --eval, --print, or STDIN
. So it would no longer throw in this case, which maybe isn’t breaking?
Perhaps the better question is whether we would still need --input-type
in the new mode. Like say we ship --experimental-type
; would there be a reason to ever run node --experimental-type=module --input-type=commonjs ...
? I guess maybe if you want an --eval
string that’s CommonJS, but also want any files on disk that it may reference to be treated via the ESM-first semantics. Not sure when you would want this, but it’s at least a potential use case.
A simpler way to put it: if --experimental-type=module
becomes the new Node-wide default, would there be any reasons to run node --input-type=commonjs
rather than node --type=commonjs
?
I think that's a case of "Just because you can doesn't mean you should." Yes, theoretically that may be a case a user may try to do, but is that something we want to actually support? Or should we just have a switch on all cases? Seems to me a lot less confusing to just have a process wide switch of everything from CJS mode to ESM mode.
is that something we want to actually support?
No, unless there’s a plausible, reasonable use case. Which there may very well be! That’s my question, can you think of one?
I would rather not support it until someone asks for it than try to invent some scenario that a user may never actually do. It's a lot easier to add support for something than it is to remove it. We should be very intentional and feedback-driven by things like that.
Well except that in this case it’s hard to add support for it if we’ve already redefined --input-type
.
I think if we want to potentially use --input-type
and enlarge the scope of what it covers, the way forward would be to create a temporary new flag --experimental-input-type
that has the broader set of behaviors; and when we’re ready to call it stable, we move those behaviors down into --input-type
. What do you think?
Alternatively we create --experimental-type
and eventually --type
, and deprecate (maybe just docs deprecate) --input-type
.
I think it's a bit confusing having a stable and an experimental flag with the same name, other than the experimental prefix. Perhaps a new flag with an additional prefix like --experimental-file-input-type
with it documented explicitly as being planned to merge with --input-type
when it reaches stable too?
"input" implies stdin, which is why the name was chosen.
why not something like --default-module-type
?
Perhaps a new flag with an additional prefix like
--experimental-file-input-type
with it documented explicitly as being planned to merge with--input-type
when it reaches stable too?
I guess? Would it be a semver-major change to expand the responsibilities of --input-type
? Because if so, that’s a good reason to choose a new flag name, so that this new flag can get backported once stable. Like we could have --experimental-type
, make it stable as --type
, and then backport --type
back to 18; whereas we can’t backport the changes to --input-type
.
Like I said, I don't feel like expanding support should be considered a major there. It's up to the TSC though. 🤷🏻♂️
Like I said, I don’t feel like expanding support should be considered a major there. It’s up to the TSC though. 🤷🏻♂️
I asked at today’s TSC meeting and several people thought that expanding the scope of --input-type
would likely be a breaking change. I suppose you could do node --input-type=module --eval 'import("./file.js")'
and in current Node, with no package.json
file nearby then that file.js
would be interpreted as CommonJS; but suddenly --input-type
gets superpowers and now file.js
is interpreted as ESM. This seems like it would be a breaking change.
Personally I want to backport this flag as far back as possible, especially to 20.x, so I’d rather pick a new name than overload --input-type
but be prevented to backport. So I guess we can rule out --input-type
, but great idea!
@guybedford https://github.com/nodejs/node/pull/49869#discussion_r1336521326:
This seems to be the better naming IMO. Using the term “default” to describe this mode switch I think may be much more clarifying since this doesn’t override existing configurations.
I considered this name, but I’m not sure users will interpret the name “default” the way we do. Especially since we want to change Node’s default module system in the future. The “default” is the value, commonjs
or module
, and that’s going to change; and it’s weird to say that “the default value of --default-type
is now module
.”
the default value of --default-type is now module
Semantically this is entirely correct in it being a default of a default, but you would usually just say the "default type" is now module.
My concern specifically was about users wondering why node --experimental-type=commonjs x.js
doesn't work when you have a package.json of "type": "module"
. Thinking of it as setting the type is definitely wrong and confusing, as it is very much setting a default.
Thinking of it as setting the type is definitely wrong and confusing, as it is very much setting a default.
I don’t think of this as any different than the type
field itself. That field only controls the interpretation of ambiguous files—.js
—and not the explicit .mjs
and .cjs
ones.
Likewise, --type
controls the interpretation of ambiguous package scopes (no type
field, or no package.json
, etc.). Just as the type
field doesn’t override the interpretation of .mjs
files, --type
wouldn’t override the interpretation of defined type
fields.
Just as the
type
field doesn’t override the interpretation of.mjs
files,--type
wouldn’t override the interpretation of definedtype
fields.
I think this is a bit counter intuitive, as usually CLI flags have the higher priority – ecosystem packages that offer configuration from package.json
will often let users overrides the package.json
config with a CLI flag.
I don’t think of this as any different than the type field itself.
I understand the reasoning you're making, but it's still not a strong argument to me. We should evaluate the clarity of the name on its own merits not relatively.
--experimental-default-type
remains my preference for clarity.
I think it’s a subjective call and we should see what the majority of people think. Personally I like the brevity of --type
once this goes stable.
If we want something that’s more specific that avoids the confusion around “default,” we could use --implicit-type
to get across that it’s only affecting ambiguous cases. But also keep in mind that this flag has other effects that aren’t so easily categorized: it bypasses the CommonJS loader and its monkey patches, and it (as currently proposed) interprets the CLI entry point as a URL. It’s more like “change a bunch of things in Node to be ESM-first.” Calling it simply “type” provides less of a clue as to what this flag does, but since it does several things at once that’s maybe more appropriate?
Seems to me expanding the scope of input-type is breaking. But also, as Jordan mentioned, "input" suggests STDIN, so not appropriate. --type
seems the best choice as it mirrors many existing conventions.
@JakobJingleheimer the recent discussion is about --type
vs --default-type
vs --implicit-type
for the new flag. I think we've established that --input-type
is a separate discussion.
--implicit-type
would also work for me here in being a qualifying name. If we want short flags, we could add a short flag alias for the module value or similar.
I like the idea of a short flag. What about -m
for --type=module
?
I like the idea of a short flag. What about
-m
for--type=module
?
I think that's fine, but first we need to decide what the name of the long flag should be. Are you saying you prefer --type
to the other options?
I don't really have a preference. If there is a short version, it wouldn't matter to me.
I don’t really have a preference. If there is a short version, it wouldn’t matter to me.
Once the module
value becomes the default, it won’t make sense to have a short version that means --type=module
(or whatever the name becomes); then we would need a short version that means --type=commonjs
, and -c
is already taken. We could have -t=commonjs
but I’m not sure it makes much sense to have a short flag that takes a value.
I also value the shortness, which is why I was leaning toward --type
in the first place. If it helps people, in my mind I think of it as meaning “tell Node to operate in type: module
mode.” As in, it’s not specific to any particular package scope, it’s a global Node setting.
To reiterate my concern about the name here - having a flag that does not do what it sounds like it does is a recipe for user confusion. If I see a flag called --experimental-type=module
and run node --experimental-type=module x.js
where depending on various complex rules I don't understand it may or may not actually execute the module under that type, creates a very bad user experience by setting up the possibility for a confusion leading to a mismatch between expectations and the actual model.
Therefore my request is that we use any name other than --experimental-type
or --type
. Both --default-type
and --implicit-type
are fine by me.
Since this is now blocking https://github.com/nodejs/node/pull/49869, and @GeoffreyBooth is unable to change the PR without consensus, I would like to ask those participating here to urgently help in finding consensus on a suitable name.
Those who have already voted for --type
(@JakobJingleheimer ?) can you clarify if you would be able to change your opinion?
And if anyone has strong opinions for or against here please do share, since not knowing which alternatives are viable is hindering progress currently.
I added an emoji vote to the top post: https://github.com/nodejs/node/issues/49541#issue-1886225536. Please vote so that it’s clear what option(s) you support. I’m happy to go with whatever gets the majority, and I would ask that everyone respect the will of the majority and not block if your preference isn’t chosen.
Can this be just a boolean? --experimental-esm-by-default
/--esm-by-default
/--no-esm-by-default
? That probably reduces the ambiguity to the minimum.
I would ask that everyone respect the will of the majority and not block if your preference isn’t chosen.
FWIW I would encourage anyone who feels strongly against a proposal to speak their mind, no matter if it's the choice of the majority, and block the PR accordingly if necessary. As long as you provide reasonable arguments against a proposition, the project should not move forward with it until the objection is resolved.
Can this be just a boolean?
--experimental-esm-by-default
/--esm-by-default
/--no-esm-by-default
? That probably reduces the ambiguity to the minimum.
If we are serious about flipping the default in the future, we should probably use --no-commonjs-by-default
. We might technically need to create such a flag in order to create a short alias, so we'll probably come back to this proposal when we try to create the alias.
@JakobJingleheimer the recent discussion is about
--type
vs--default-type
vs--implicit-type
for the new flag. I think we've established that--input-type
is a separate discussion.
I got that, thanks ;) I was merely omitting the experimental
prefix because it was already established to be in all cases.
default
and implicit
seem a tad verbose: all the existing machinations assume CLI flags to be the value unless something more specific overrides it. So the extra words seem like noise to me.
If a collaborator really feels like extra verbiage is needed to re-assert established behaviour, sure. For probably a majority of usage, it'll be a set-and-forget in some config file, so no need to lose sleep over it—I think all the proposed options convey what they'd do. If there needs to be a tie-breaker (it looks close), my ranked vote is:
--experimental-type=module
--experimental-esm-by-default
Now that --default-type
has landed, I think it would be good to land a short flag. Besides the UX, it would help in marketing efforts. A few people have mentioned that -m
seems like the obvious choice, as a shorthand for --default-type=module
.
The inverse would be -c
, which is already taken as a shorthand for --check
. How about:
-m
as a shorthand for --default-type=module
.-c
; the message would say to use --check
instead.-c
as a shorthand for --default-type=commonjs
.We could also just forgo having a short flag for the “back to CommonJS default” option.
Shipping a short flag for an experimental flag sounds like a mistake, the whole purpose of putting experimental-
in the flag is so it discourage users from using it. Adding a short version should not happen until the flag is stable IMO.
Shipping a short flag for an experimental flag sounds like a mistake, the whole purpose of putting
experimental-
in the flag is so it discourage users from using it. Adding a short version should not happen until the flag is stable IMO.
Well if we think we want short flags in 22, and if we want -c
to be one of them, then we should start the deprecation cycle now for -c
.
Can't we just switch to another shorthand instead of deprecating -c
for --check
unnecessarily? I am pretty sure it's common for tools to just pick a different shorthand flag when there's a conflict of existing flag. We can't just keep shifting flags randomly around, there are always too many words and too few latin letters.
We also don't necessarily need to come up with a short flag for commonjs
I’d dispute that; I’ll forever want to keep my default type as it is, commonjs.
Shipping a short flag for an experimental flag sounds like a mistake, the whole purpose of putting
experimental-
in the flag is so it discourage users from using it.
I don’t think we’re trying to discourage users from using this flag, in fact the opposite. We’re just trying to emphasize to users that it’s subject to changes.
The appeal of -m
is that since we ended up with a mouthful of a flag, --experimental-default-type
, we could use -m
in the announcement as a more concise and memorable way of explaining the new feature. But there’s no point to using -m
once the default is flipped. The time when -m
is useful is during the lifetime of 21 when this flag exists and the default is still commonjs
.
But if we don’t ship -m
before the default flips, it would follow that we wouldn’t have a short flag for the commonjs
value. It might be confusing or feel like a mistake to have a short flag for one value and not the other. -c
seems like the obvious choice for a short flag for commonjs
, and I think --check
is so rarely used that very few people would notice if we repurposed its short flag; especially if we used all of 21 as a deprecation cycle.
So anyway I think either we deprecate -c
and ship -m
for module
now in 21, and then point -c
at commonjs
in 22, or ship no short flags. I’m not sure any other plan makes much sense?
I think changing an existing flag is pretty annoying for people. I’d prefer if we do not want to do that.
Building off of https://github.com/nodejs/node/issues/49432, what should the flag be named for this proposed new mode? Yes, this is the bikeshed thread.
I think we have a few constraints:
--experimental
(for now, until it goes stable).--input-type=module
/--input-type=commonjs
; or have an obvious opposite, so that if/when this new mode becomes the new Node default there’s some way to opt back into the previous CommonJS-first behavior.module
andcommonjs
for consistency with the existing--input-type
and thepackage.json
"type"
field.--experimental-module
because there was a prior flag named--experimental-modules
which still exists as a noop, and it would be confusing to users if nothing happens when they try to use the flag but made a typo.Please vote using emoji:
--experimental-type=module
/--experimental-type=commonjs
--experimental-default-type=module
/--experimental-default-type=commonjs
--experimental-implicit-type=module
/--experimental-implicit-type=commonjs
--experimental-esm-by-default
/--no-experimental-esm-by-default