Skip to content
This repository has been archived by the owner on Sep 2, 2023. It is now read-only.

Feature: Provide a way to make ESM the default #318

Closed
GeoffreyBooth opened this issue Apr 25, 2019 · 4 comments
Closed

Feature: Provide a way to make ESM the default #318

GeoffreyBooth opened this issue Apr 25, 2019 · 4 comments

Comments

@GeoffreyBooth
Copy link
Member

Some users will want to rush forth into the ESM-only future and work with Node as if ESM were the default instead of CommonJS.

Use cases

  1. Loose extensionless or .js files that contain ESM syntax, where the user doesn’t want to use @WebReflection’s clever shell scripting or create symlinks to .mjs files or .js files inside an ESM package scope.

  2. More convenient --eval or --print, e.g. node -e 'import "foo"' rather than node --input-type=module -e 'import "foo"'.

Implementation

I’m assuming that the general way to do this would be to introduce a new flag to go in NODE_OPTIONS. I think a logical name would be --default-type and it would take commonjs or module, just like --input-type. The question is what the behavior of --default-type should be:

  • It could set the default mode for --input-type and stop there. This would solve the second use case but not the first.

  • It could do the above and also set the default mode for files outside of any package scope (i.e. Node crawls all the way up to the volume root without finding a package.json to govern the file). This would solve both use cases.

  • It could do the above and also set the default mode for the package scope around initial an entry point. In other words, a user’s project with no "type" field would be treated as ESM, but any dependencies in that project’s node_modules that lacked a "type" field would still be treated as CommonJS. This would provide the most feeling like ESM was the default to be opted out of rather than into, without breaking all over the place if it also applied to dependencies. I don’t know what the use case for this would be, though; adding "type": "module" to a package.json doesn’t seem like such a burden that we need a flag to opt out of needing to do that.

  • It could do the above and also set the default mode for all package scopes that lack a "type" field. This would flip all defaults, everywhere that CommonJS is currently defaulted to, but projects would be broken until all dependencies had a "type" field declaring themselves to be either ESM or CommonJS (or a package manager added such a field automatically). There’s no use case for this either that I can think of, though it’s the most “pure” in that it would show what a future Node would be like where CommonJS were deprecated.

@devsnek
Copy link
Member

devsnek commented Apr 25, 2019

can you remove --eval from this? i think it should use repl mode (assuming repl mode moves forward) which would remove it as an issue for us entirely.

@GeoffreyBooth
Copy link
Member Author

can you remove –eval from this? i think it should use repl mode (assuming repl mode moves forward) which would remove it as an issue for us entirely.

Wouldn’t that be a breaking change for --eval? I would think if that change were to happen, it would be via --input-type=repl so as not to break any shell scripts that depend on the current behavior. And then you still have the issue of how to make --input-type=repl the default instead of --input-type=commonjs, which is more or less the same as the desire to make --input-type=module the default.

If --eval (and --print and STDIN) are changed to take the REPL mode by default, sure, I’ll change this; but I don’t want to assume some theoretical future, especially a hypothetical breaking change. If that change happens after we implement --default-type, then --default-type could also change.

@weswigham
Copy link
Contributor

weswigham commented Apr 25, 2019

I wrote a hypothetical ecosystem migration strategy here:

Take this reasoned transition plan, for example:

  1. type field is available unflagged in node 12. npm --init starts to generate package.json files with "type": "module" set.
  2. node 13 - warn on packages without "type": set to a known value ("module" or "commonjs"). npm automatically adds "type": "commonjs" to packages missing the field on installation, so most people don't actually notice the change.
  3. node 14 - "type": "module" or "type": "commonjs" is now a required package.json field.
  4. node 15 - Packages missing a "type": field are now assumed to be "type": "module" by default. npm now automatically only appends "type": "commonjs" to packages last updated prior to a specified cutoff date (and does nothing to modern packages).

This would advance the ecosystem default in a relatively easy-to-handle way, IMO, with npm's coordination.

@GeoffreyBooth
Copy link
Member Author

See #335 (comment)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants