-
Notifications
You must be signed in to change notification settings - Fork 43
Conditional exports as flags #428
Comments
Which such a system in place you could consider additional conditions like:
This would make it possible to |
Transferred to the modules repo for discussion. The syntax of specifying the target / usage at the top level is sugar that was added last minute... export keys are often defining deep imports, which can make this pattern get super verbose. The following isn't supporting but is something discussed in the last meeting "exports": {
".": {
"node": {
"require": "./node-cjs.js",
"default": "./node-esm.js"
},
"browser": {
"require": "./browser-cjs.js",
"default": "./browser-esm.js",
" any-key-you-want": "./wat.wasm"
}
},
"./feature": {
"default": "./lib/feature-umd.js",
"node": "./lib/feature.mjs",
"whatever-you-want": "./lib/feature-in-weird-format.whatever"
}
} To be honest I am not totally sold on the current default condition names but have yet to come up with something better... time to think about this a bit more 😇 |
I have to admit that I somewhat lost track of which conditional features we removed. Nested conditionals are actually something that "just worked" initially because it naturally fell out of the recursive definition of export mappings. The intention was definitely that
I would call all of them "environment constraints". E.g.
Feature detection is super interesting in general. There were some earlier discussion here, including testing for specific APIs: jkrems/proposal-pkg-exports#29. I don't think we've fully determined where we'll ultimately draw the line, especially because there is a risk that a library being too aggressive in pre-processing its code could actually lead to issues when trying to optimize for environments on the app side. So I'm very tempted to prefer something like "source" or the "featureset2019" idea promoted by @mathiasbynens which could cover things like WASM implicitly (not sure if there are good docs on it..?). |
|
Do you mean "require is a flag that isn't consistently set across the whole process"? To me node has effectively two "environments" now: The require environment and the import environment. Each is following its own rules. So from that perspective, |
@jkrems i ask because this may impact response to https://github.com/littledan/proposal-module-attributes which does allow setting key/value pairs |
Ah, thanks for clarifying! So, straw person: // Usage:
import("ui-library", { prefer: ["purple"] });
// ui-library/package.json
{
"exports": {
"purple": "./theme-purple.mjs",
"default": "./theme-default.mjs"
}
} My gut feeling is that user code should use specifiers to express what they are looking for. If module attributes ends up as something more generic (e.g. |
Nested conditions do fall out of both the current spec and implementation, and composition in this was is definitely an important feature. Nesting was the simplest implementation and spec to achieve this given that it was work not to include this feature! We could well consider a There are also plans to open up setting the environment conditions when running Node.js - something like |
Ok seems like we are on the same direction. I think I will start implementing |
@sokra that would be really great, and please do provide your feedback here. Implementer feedback from tooling is exactly what we were hoping for before unflagging these conditions for January. |
I'd also mention the package.json#targets proposal which allows package authors to define arbitrary targets and let tools read this metadata to decide which entry to choose. The existing conditions are mostly to do with the environment the code runs in (browser, node, CJS, ESM), but if, for example, you wanted to have multiple of those for different versions of browsers or node, there's no way to do it. This was originally proposed in the Parcel 2 RFC. Our alpha releases currently support it for building multiple targets, but not yet resolving other packages in node_modules using the same rules. I would like to get buy in from other tools around this. |
I'd like to us to also reconsider based the direction of these requirements if it makes sense to offer flat/hybrid lookups. Simple example ( {
"exports": {
"./": "./",
"./@browser": "./browser/",
"./helpers": "./helpers.js",
"./helpers@browser": "./helpers.js"
}
} Flat/hybrid lookups make it easier to write the lookup logic as The added cost for platforms with limited capacity can be eliminated during parsing (ie in a Just a thought :) |
One possible downside of encoding additional information in the specifier (especially after |
@jkrems certainly, so I opted for |
this specific request is available as |
Is your feature request related to a problem? Please describe.
Currently node supports three "conditions" for resolving conditional exports:
require
: For usingrequire()
instead ofimport
node
: For targeting nodedefault
: as general fallbackFor other tooling other conditions are recommended:
browser
: For targeting the browser.electron
: For targeting electrondeno
: For targeting denoreact-native
: For targeting react-nativeI would argue that these conditions fall into two orthogonal categories:
target
andusage
.i. e. one could use
require
while targetingnode
, or one could userequire
while targetingbrowser
.Currently it's a bit unclear if
require
means usingrequire()
in node.js or usingrequire()
in general for any target.If it means
using require() in general for any target
there would be no way to target only CJS usage in node.js.If it means
using require() in node.js
we probably have to get creative when somebody wanting to target CJS usage in browser, i. e. with a new conditionbrowser-require
. But this also means it would become inconsistent with the node conditions and cause user confusion:Why is "require" not used for my frondend package?
Example
Describe the solution you'd like
Treat conditions as flags and allow combinations of them.
One solution could be to separate combinations with
+
, which would result in a minimal change I would recommend:This would allow other tooling for support combinations of
require
with other targets:Describe alternatives you've considered
Other separators would also be possible: i. e.
node-require
ornode/require
.It's possible to restrict the allowed order of conditions, i. e.
target
must come beforeusage
.It's also possible to use nested objects to specify combinations of conditionals, which isn't that bad, but more verbose:
Now that I see that, I may like it a little bit more... But it's a bit more work to implement that.
cc @guybedford
cc @lukastaegert for rollup
The text was updated successfully, but these errors were encountered: