Trailing slashes #244
Description
@RReverser pointed out to me today that in Node.js, you can do either require("lodash")
or require("lodash/")
, and both will map to the lodash package's main module.
Similarly, in Node.js you can do either require("./directory")
or require("./directory/")
, and this will look for the "main"
field in ./directory/package.json
and require that module.
With import maps, these trailing slash variants are not possible to remap in the same way. We currently require trailing slashes to match, so you can do "lodash/": "/node_modules/lodash/"
and "./directory/": "./some/other/directory/"
. But then, importing those will give URLs like https://example.com/node_modules/lodash/
, which is not what you want; you wanted the URL to be https://example.com/node_modules/lodash/main.mjs
.
Another aspect to consider is if we introduce import.meta.resolve()
. What should the result of import.meta.resolve("lodash/fp/..")
be? As currently proposed, it would be whatever URL "lodash/"
maps to. Which, per the above, is not so useful.
So the first question is, do we care about this case? I'm inclined to take a wait-and-see approach. In particular, my initial instinct is that even though Node has two ways to require the same module, "lodash"
and "lodash/"
, maybe it's OK that on the web only the first way works. I'd be open to changing this opinion as we see more people running into issues in the wild.
Then, if we did want to address this, how would we? Simply lifting the "slashes must match" restriction is not great, because what if you want both "lodash/" -> </node_modules/lodash/main.mjs>
and "lodash/foo.mjs" -> </node_modules/lodash/foo.mjs>
? You wouldn't be able to get both.
One route for addressing this, which is attractive to me, might be to try to canonicalize all trailing slashes in import specifiers away. That is, "lodash/"
literally means the same thing as "lodash"
. This is trickier for cases like "/directory/"
; it'd be a breaking change (but maybe a web-compatible one?) to always treat that the same as "/directory"
, i.e. change it to by default request the URL </directory>
instead of the URL </directory/>
. Maybe we could only impose the normalization when an import map gets involved? But that might be a bit messy.