Note to people reading this: module support in this post seems to mostly refer to the
loading of modules. The spec is pretty clear about the syntax and semantics of modules,
except when it comes to loading which it more or less says is "up to the runtime" to figure out.
There's some interesting (or not, depending on your POV) conversation/debate going on between the nodejs world and the browser world, which are – I suppose – the only two "real" runtime environments where JS is widely used.
There's a lot of effort going into figuring this out, but from a lowly developer point of view it's increasingly frustrating to see that two years on from when the module standard was ratified, we still have to resort to compiling modules to a yesteryear solution such as AMD, CJS, or even globals – or, if you're so inclined, all at once via UMD.
One big issue in figuring this out, as far as I understand it, is determining whether some JS code is ES2015+ or not, since the semantics of loading such a module changes. It may sound simple, but there's plenty of situations where the answer is ambiguous, but picking the wrong answer will result in a change of behavior for older code. Since TC39 is very wary of not breaking backwards compatibility (and kudos to them for it!) simply saying something like "assume ES2015" just won't do.
There was a proposal to change the module semantics to require ES2015 modules to include at least one import or export statement, since these would break in pre-ES2015 runtimes, removing any ambiguity in the syntax. Unfortunately, it seems this proposal is all but dead at this point. (And probably for good reasons I simply don't know about.)
DISCLAIMER: I may well be incorrect about the details in the above, but I think the overall picture is more or less correct.