>There are already tons of browser libraries not using the .mjs extension.
Browsers don't care what extension you serve something as, so we can't really directly match that in the default behaviour. What you can do is use a resolve hook to tell node to interpret certain files as esm even when they don't have a `.mjs` extension.
>Not clear to me why just using 'import' makes it a module and 'require' not.
import doesn't "make something a module". if you try to require something that resolves as being esm (rn we check that with .mjs) it will throw, because esm resolution is async and require resolution is sync. You can't require esm but you can import anything.
Why does import have to work with cjs? It doesn't in the browser. Why does require have to work esm?
Why not just have a package up it's major semver and those packages that want to start using it need to import it? That seems no different than the browser. AFAIK you can't import a non-module and you can't non-import a module in the browser or am I wrong?
Let this be solved in userland through compilers, like everyone already does today. The stubbornness from current node maintainers on this subject is astounding. Years of feedback, like you see in this thread, ‘but-what-if’ and ‘you-dont-get-it’ handwaved away.
> Not clear to me why just using 'import' makes it a module and 'require' not. I'm sure that's spelled out somewhere
I'm probably wrong but I think it has to do with parsing rules. If you try to load a module as CJS and hit incompatible syntax (e.g. keywords such as import or export) then it has to restart parsing from the top. Likewise, if you parse the file as ESM but hit CJS syntax such as `exports.foo = bar` then again it has to restart.
There are probably a bunch of similar issues but if I recall correctly it basically came down to parsing and performance, you don't want to load the same thing twice essentially. With a special extension you don't have to even load the file before deciding which parsing rules to use, supposedly making this more efficient.
I've heard several proposals to resolve this issue, but my favorite two are probably the unambiguous module syntax and making import/require only compatible with their respective module formats. The first would be a breaking syntactic change, in that every ESM module would be required (no pun intended) to include the top level `export` keyword at least once, regardless of whether or not the module actually exports anything. The second would be to make node's `require` function only compatible with CJS modules and make the `import` keyword only compatible with ESM. Both of these have drawbacks of course, but I'd like to think they're mostly temporary and rather easily overcome. The unambiguous module syntax less so perhaps, but still.
the other issue was that a module that doesn't import, export or require anything and doesn't specify strict mode will get parsed differently depending on whether it is a CJS or an ESM and their is no in band way of telling which is which
That’s right, thanks for the reminder! Some syntax is ambiguous yet results differ. I think that’s why I liked the unambiguous module syntax very much, it made things explicit, without much cost.
As do I. I loathe it. But I'm struggling to come up with strong rational reasons why. Part of me says that hurts interoperability, but I think that's mostly rationalization.
Why do I care so much about a file extension? Because I really really do.
The reason I care is because effectively node is imposing it's standards on the browser. Effectively node is requiring all browser based modules to use .mjs even though they shouldn't have to care. Except they will care because they'll start with .js, the make an npm package, then someone will want it to run in node, then it has to be renamed .mjs, then all non node projects are effected only because of node's chosen solution. It seems bad to me for node to effectively bleed it's problems on the entire JS ecosystem
> One of the goals of the Modules Team is “browser equivalence”
There are already tons of browser libraries not using the .mjs extension.
Not clear to me why just using 'import' makes it a module and 'require' not. I'm sure that's spelled out somewhere