-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
Description
Affected URL(s)
https://nodejs.org/api/packages.html#conditional-exports
Description of the problem
I'm coming here from evanw/esbuild#1956. Specifically the esbuild bundler implements node's spec for exports
in package.json
files. Node's documentation for exports
says this:
"import"
- matches when the package is loaded viaimport
orimport()
, or via any top-level import or resolve operation by the ECMAScript module loader. Applies regardless of the module format of the target file. Always mutually exclusive with"require"
."require"
- matches when the package is loaded viarequire()
. The referenced file should be loadable withrequire()
although the condition matches regardless of the module format of the target file. Expected formats include CommonJS, JSON, and native addons but not ES modules asrequire()
doesn't support them. Always mutually exclusive with"import"
."default"
- the generic fallback that always matches. Can be a CommonJS or ES module file. This condition should always come last.
This is what esbuild implements. The case I'm looking for clarification on is that there are packages that just have require
and import
but not default
. This is reasonable as the example in the documentation also doesn't include a default
condition, and the documentation says import
and require
are mutually exclusive (i.e. exactly one should be present).
However, esbuild performs the following kinds of path resolution:
import-statement
require-call
entry-point
import-rule
url-token
I understand what should happen with the first two but not with the last three. An entry point is path resolution that happens due to a package name provided on the command line. There is no import or require in that case. And the last two happen when you import things from CSS (something a bundler has to deal with) where there is also no JS import
statement or require
call. If esbuild supported importing things from HTML, which it may one day, there would also be those cases to consider.
Right now esbuild handles these non-JS cases by still running the exports
logic but just without the import
or require
conditions active, since it's neither an import nor a require. But then that breaks when there's no default
condition. Do you have any opinion for what should happen here, as the authors of this specification? Some options:
- Don't apply
import
orrequire
and fail path resolution if nothing applies (esbuild's current behavior) - Don't apply
import
orrequire
and fall back to legacymodule
/main
fields if nothing applies - Pick one of
import
orrequire
to apply arbitrarily - Apply both
import
andrequire
- Don't attempt to apply
exports
rules at all and only use legacymodule
/main
fields - Undefined: up to the tool to do whatever they want
- Something else?