Define differential mapping support in exports #357
Comments
Why arguably? The reason for import maps in browsers to support that is because it's loading things over the network, which isn't what node will be doing. |
Network errors are more of an anti-feature of import maps. I genuinely hope that support for handling network errors is removed from import maps. What it does allow is to say "I'm a polyfill for a built-in module, only load me if the native implementation doesn't exist". Or hopefully in the future true differential serving, e.g. based on platform or production/development as mentioned above. |
ah - ok, so i can see optional deps working like this, like |
There's some finer details when it comes to bare specifiers in values (since the resolution is generally not recursive). But assuming we'd have a new built-in module for mime, you could do something like The more exciting thing would be if the array would support guards beyond "standard module with this URL exists". E.g. with strawman syntax: [
// "Load only if env is set to development"
{ env: 'development', path: './dist/dev.js' },
// "Load if none of the entries above matched"
'./dist/prod.js'
] This solves one important gap in ESM which is the absence of a way to load modules based on the environment. Top-level await with dynamic import still requires a lot of boilerplate to make that work, especially if there's more than one exported binding. |
It might be useful to defer arrays, and objects in them, to future proposals/PRs - but ensure that they're errors right now, so that nobody starts using them in the meantime. |
@ljharb if we were to throw for arrays / objects in exports, then that would effectively stop any backwards compat for these being supported in future though. |
@guybedford can you explain? I took the comment to mean that it would ensure versions not supporting the Object/Array forms wouldn't silently ignore those values. If we silently ignore values that means that users can come to rely on that noop. |
When the matched target is an unknown value / type, yes the only thing we'd want to do is likely throw. There are a few cases in play here, and the cases to reason about more graceful handling require exact proposals in mind - I will spare the process of going through all the examples, but the important thing is that where possible, backwards compat can be as graceful as possible as opposed to blocked. |
We'd definitely want to support arrays asap because otherwise any library trying to use fallbacks would have to wait until node 12 is completely out of support. The general design of import maps suggest to me:
Throwing means not being backwards-compatible in this case. Because the point is that earlier entries win and new features can only be introduced if they are ignored on older versions. |
To illustrate how those steps help, here's a package published just after the latest version of node added support for [
'std:fetch', // versions that don't support std: URLs will skip this. latest node and browsers will use this one!
'nodejs:fetch', // versions that don't support nodejs: URLs will skip this. versions that do support this URL will use this one!
'./fetch-polyfill.js', // any version with step 1 support will reach this one and - since it resolves to a file URL - will use it.
] |
There's some improvements of the base array syntax that @guybedford wrote up in https://github.com/guybedford/proposal-pkg-targets. |
Replaced with #401 |
Right now
exports
only supports simple strings. Arguably it should also support arrays of strings just like import maps.A stretch goal would to also support additional signals for differential mappings. E.g. having a mapping based on platform/OS or a production and a development build.
Since we're using
main
as an extension of theexports
mechanism, this would potentially also affectmain
values.The text was updated successfully, but these errors were encountered: