The .mjs extension isn't required in browsers, but absolute paths are.
So even if the .mjs extension requirement is dropped, I don't think the implication is that './foo' can successfully resolve to './foo/index.js' as there is no such thing as a directory in HTTP and you don't want browsers to make multiple guesses for which path exactly exists.
Isn't the absolute path (not exactly true, since dots are supported) thing just a matter of punting till later? If I recall correctly, they couldn't agree on resolution rules and perhaps more specifically how node-like rules would translate to the web, so they punted and went for an "absolute or bust" kind of approach till someone comes up with a better idea rather than painting everyone into a corner. Mapping identifiers and path resolving functions have been suggested as ways to make identifiers "nicer" I think.
This seems reasonable. I reckon the reason why node's behind on figuring out how to make ESM work is because of all this implicit loading magic, and a reluctance to break existing code. (A commendable goal I think.)
Except no? Only servers where stuff making requests expects the server to behave that way. The interesting thing about this is that every server in the world already works like this: they expect the person calling the server to know how the server works.
You know what, I had completely forgotten about that, and it completely changed my view.
Sure, we can have webservers serve up different thing based on parsing the url (a GET for `/users` could return `/users/index.mjs` if it wants), but having that required by the spec would be a mess, and not having it in the spec but still allowing it in node would cause annoying bugs when trying to use a library on both sides.
This is a pretty ubiquitous web server behaviour already.
If you link to /foo and it happens to be a directory, the server redirects you to /foo/. It then looks within the corresponding directory for an index file and serves that.
Most web servers have this as the default configuration, but the default list of potential index files doesn't include index.js (it's usually just index.html or index.html index.htm default.htm etc). It's usually a one line change to include index.js. This has worked fine for decades; there's no need for including this in the JavaScript spec. – it's up to whoever wants their server to respond that way to configure it appropriately.
But if node.js were to use a different default of how to do filesystem lookups (look for foo.js, then fallback to foo/index.js if not found), then you'd start seeing modules which wouldn't work on the web without the web server setup to use that exact same system. That's now an implicit contract.
This is in all honesty a small problem in the grand scheme of things, and it's one that can be equally solved by better editor tooling (for auto-refactor filenames abilities that also change all imports, since imports are for the most part statically analyzable now)
> But if node.js were to use a different default of how to do filesystem lookups (look for foo.js, then fallback to foo/index.js if not found)
They won't do that because they are clearly intent on having code work between environments. They repeatedly tell people this whenever people complain about .mjs. So we can discount this as a possibility.
> you'd start seeing modules which wouldn't work on the web without the web server setup to use that exact same system. That's now an implicit contract.
The inverse is true for their .mjs solution, which is essentially "Use Node's .mjs on the web or shared code will break in Node". This requires adopting the Node naming convention on the web and altering web servers to serve .mjs files as application/javascript. The .mjs file extension isn't a standard and doesn't make sense on the web; ESM modules are both of those things. If you think changing web server configurations for an implicit contract is not acceptable, you should be against .mjs.
So even if the .mjs extension requirement is dropped, I don't think the implication is that './foo' can successfully resolve to './foo/index.js' as there is no such thing as a directory in HTTP and you don't want browsers to make multiple guesses for which path exactly exists.