Description
I think there’s something to be said for "mode"
as a general type signifier, similar to the function served by a file extension. Just as .json
tells you the type of a JSON file, but not how or with what to open it, something like "mode": "esm"
is “pure” metadata that describes the type of the package rather than configuring Node how to process it.
Remember that NPM packages are used not just by Node; plenty of browser libraries are published to the NPM registry nowadays. A browser
package type actually makes a lot of sense. A package with "mode": "browser"
would not be importable by Node at all, either in CommonJS or in ESM modes, as this NPM package simply isn’t intended for Node to use. Perhaps a loader could register itself to handle "browser"
packages, and supply things like a global window
object and emulated DOM.
Another possible type could be meteor
. The Meteor platform maintains a separate package registry, https://atmospherejs.com/, to hold Meteor packages since they’re not importable by Node (as they have separate entry points for client and server). A "mode": "meteor"
could be a way to bring them into the fold. cc @benjamn.
Likewise, packages can be flagged so that they’re only ever imported by a build tool, whether the Meteor build tool or something like Babel. A package that intermixes CommonJS and ESM syntax in the same files, for example, could be "mode": "babel"
to signify that Node should not be able to directly import it but that it needs to be used only as part of a Babel build chain (or with the Babel loader registered).
The list goes on. I think there’s utility in keeping file extension mappings and this “package type” concept separate, so that for example loaders can register to handle packages of certain types without being limited to sets of file extensions. Keeping the configuration short and sweet like "mode": "esm"
or "type": "browser"
allows flexibility in the future, as we can expand what’s covered by this property.