Current ES6 module usage (and general JS usage) in the browser relies on transpilation (due to non-widepread support in browsers) and bundling (to limit HTTP request count and HTTP waterfalls) for performance (module count easily goes into the 1000s which even with HTTP2 cannot be efficiently loaded in a module-per-request strategy; even when using Push to avoid HTTP waterfalls).
The bundlers use 2 large classes of strategies to bring N modules into a single JS file:
- (require.js, browserify, webpack): Each module gets put into a function that can be addressed by name. There is typically an export object per module where all exports are properties of that object.
- (closure compiler, rollup): Modules get compiled away and exported symbols become essentially global variables (at least within compilation unit) and directly accessed by other modules.
Approach #1 has the benefit of being simple and allowing easy late loading (late loaded JS can access already loaded modules by name). Its primary downside is that it has performance issues due to the frequent hash lookups during inital execution of JS and indirection when accessing functions from different modules.
Approach #2 undos the performance issues, but it has the problem that interop between late or concurrent loaded modules requires somehow marshalling symbols between files. Rollup does not support this at all. Closure Compiler supports it by exposing all exports to the global scope or by exposing them to a single global object (incurring a property lookup (often hash lookup as this object will have 1000s of properties) cost per access).
These approaches all share a problem that they cannot interoperate with modules from other ecosystems. E.g. one cannot put up a URL like https://cdn.foocdn.com/react.1.3.5.js that can be shared by all React users (and cached by web users) and load that as an ES6 module making it available to the bundled code as that code no longer has a notion of modules at all. Several modes of hybrid systems can, of course, be envisioned, but these would make the bundlers even more complex and they are already perceived as very complex by devs today.
Giving the reality of bundling, it would be great if modules could still exist as first class entities when grouped into a single file. One way to do it would be through a type of module keyword like
module 'name/like/in/import' {
… module content
}
module 'module2' {
… module content
}
module 'other/module' {
… module content
}
With this different compilation units gets to interact with one another one the ES6 module level without relying on potentially inefficient and hard to optimize runtime patterns.
Specify an archive format (jar, zip or similar) that allows retrieving N modules (and potentially) other resouces in a single request. The primary benefit here is independence from JS syntax.
- Use complex loaders that implement something like the proposal above at runtime invoking an eval-like function for each module.
AFAIK systemjs can do the thing you say is missing, importing a module through a cdn url