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.
Readable version: https://github.com/guybedford/ecmascript-modules-mode/tree/types
So I started rewriting the proposal to both incorporate the ideas from #2 (the concept of a “package type”) and to describe how this configuration could work for a package with multiple types, such as the most common example a “dual-mode” CommonJS and ESM package. Whether or not you want to keep the “type” language, I ran into an issue with trying to make dual-mode work:
"main"
.We can’t change
"main"
. We can’t say that going forward,"main"
can take an object like"main": { "esm": "./index.mjs", "cjs": "./index.js" }
. That would be a breaking change, and the whole point of supporting CommonJS as a target environment is to support older versions of Node that can’t import ESM.So either we accept that we’re conflating two of @guybedford’s three concerns—the package entry point (main) and the package exports (encapsulation)—or we need to introduce a new key to replace
"main"
. For the purposes of this proposal I opted to roll up the entry point as part of"exports"
, the way that the package exports proposal describes it, and the object form is supported:"exports": { ".": { "esm": "./src/index.js", "commonjs": "./dist/index.js" } }
. I think package exports and the package main entry point are very close if not joined concepts, as the entry point is basically the/
export and the others are the/path
exports, so I can see users grasping them as part of the same configuration block.Alternatively, we could introduce a new key to replace
"main"
, like"entrypoint"
. This could take the object form, like"entrypoint": { "esm": "./src/index.js", "commonjs": "./dist/index.js" }
. Then we would still get the full separation of concerns that Guy was after, albeit with duplication as now the user can specify the entry point in either this new field or in"exports"
. But I’m not sure we should be giving the user two places to define the same thing, and I don’t think we should take it out of"exports"
as the entry point really is the main export.I don’t think we should assume that most packages will have only a single type/mode, and therefore it’s okay to keep using
main
. I think CommonJS/ESM dual-mode packages will be quite common for a few years, and whatever configuration we come up with should work well for such packages. Usingmain
also raises the question of whether it supports automatic extensions and folder lookups ("main": "./index"
, or"main": "./dist/"
) for ESM or other non-CommonJS environments. It would be inconsistent either way—inconsistent if it does allow such things, as then this behaves differently from"exports"
andimport
statements; and inconsistent if it doesn’t, as then"main"
behaves uniquely for CommonJS as opposed to other environments. I think it’s best to just leave"main"
as a CommonJS-only legacy thing, not to be further abused.