Fwd: Are ES6 modules in browsers going to get loaded level-by-level?

# Wizek (3 years ago)

I've been redirected from here: tc39/ecma262#27 . Not sure if this is a good place to ask this question. If not, I'm sorry for the noise. Could you then point me elsewhere perhaps?

I've just read this post here: www.2ality.com/2014/09/es6-modules-final.html Which claims that the module system will support both sync and async loading. Which I like. But it made me wonder if/how well async loading would work for deeper dependency trees. E.g. if I had a project with 20 level deep dependency tree (at its deepest point) and my server would take on average 200ms to respond, then it would take about 4000ms minimum to execute any/all of my scripts, right? Or is there something I am missing?

If I interpret the situation correctly, what is the conceptual response to this scenario? Try to limit the tree depth? Concat everything just like it happens often with ES5? Something else?

# John Barton (3 years ago)

An async load will call for a module that knows--synchronously--its imports. The server can respond with the entire tree in one response.

The problem comes in avoiding duplicate transmission of modules shared by multiple async loads. The client will need to signal the server about the previously loaded modules.

If you search this list back to posts by Ian Hickson you can read about his HTTP/2 based discussions.

Broadly this subject is considered by "professional" web developers as just a moot point. They consider dynamic loading with decisions made in the client to be undesirable. They do support what might be called "optional" loading, where only part of the JS is loaded initially and more JS is loaded later. But the dependency decisions are all baked into the server and thus the tree of layers known only in the client does not arise.

HTH, jjb

# caridy (3 years ago)

The issue you're describing exists today, and it is the main reason why we do bundling (a la webpack, browserify, etc.).

ES6 modules are not introducing any new restriction here, it is just the way things work. HTTP2 is suppose to help in this , but only a little bit. In my experience, loading the modules is not even the biggest issue here, but executing 500 modules is, because it will require at least an order of magnitud more promises to be resolved, plus all the other normalization logic. This is where "folding" might help us. Assuming you have a huge tree of modules, we could analyze that tree and fold it into few modules that are key for the application to function, then fetching and executing those modules should not be a big deal, this is very similar to bundling as we know it today but without sacrificing module semantic, and loader advanced functionalities.

In any case, this should not prevent us from writing modules using ES6 import and export declarations today.

# medikoo (3 years ago)

It'll be great to have some more insight on this.

To my knowledge when using ES6 modules as currently specified there's no way to introduce more than one module with one file. So technically, the only way to use them natively in browsers, would be to serve them separately. This raises the question. Is there any mean in sight, that will allow us to serve them as fast as we can serve hundreds of bundled and minimized CJS modules now?

Because if not, then landscape looks troubling. As it means that to have same performance, we will need to transpile ES6 modules for browser into something else, even though browsers may support them natively.

-- View this message in context: mozilla.6506.n7.nabble.com/Fwd-Are-ES6-modules-in-browsers-going-to-get-loaded-level-by-level-tp337040p338209.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.

# Domenic Denicola (3 years ago)

Is there any mean in sight, that will allow us to serve them as fast as we can serve hundreds of bundled and minimized CJS modules now?

Yes. Any browser which implements the ES6 module loader (none of them right now) will also be a browser that implements HTTP/2 (all of them right now). HTTP/2 server push would allow you to respond to a single request for "entry.js" (e.g. from <script type="module" src="entry.js"></script>) with responses for all modules in the entire dependency graph, prioritized according to their level in the graph, all over a single TCP connection.

This is just the most naïve strategy I could think of with HTTP/2. There are more interesting ones too.

It's also important to note that bundling is an antipattern in the HTTP/2 world, as it prevents incremental cache updates by invalidating the entire bundle graph when you change a single file, and does not allow relative prioritization of individual files.

# John Barton (3 years ago)

On Thu, Apr 16, 2015 at 12:18 PM, Domenic Denicola <d at domenic.me> wrote:

Is there any mean in sight, that will allow us to serve them as fast as we can serve hundreds of bundled and minimized CJS modules now?

Yes. Any browser which implements the ES6 module loader (none of them right now) will also be a browser that implements HTTP/2 (all of them right now). HTTP/2 server push would allow you to respond to a single request for "entry.js" (e.g. from <script type="module" src="entry.js"></script>) with responses for all modules in the entire dependency graph, prioritized according to their level in the graph, all over a single TCP connection.

This is just the most naïve strategy I could think of with HTTP/2. There are more interesting ones too.

It's also important to note that bundling is an antipattern in the HTTP/2 world, as it prevents incremental cache updates by invalidating the entire bundle graph when you change a single file, and does not allow relative prioritization of individual files.

But the push scenario in your first paragraph would not use the cache either.

As far as I can tell, only the client knows which modules it has loaded; only the server knows the dependency graph for modules-to-be-loaded. So: one or the other has to send its information at the outset of a import request, or the server needs to send the entire bundle, or the loading has to be layer by layer. HTTP/2 does seem to have the magic to avoid considering these issues in module loading.

jjb

# Domenic Denicola (3 years ago)

From: John Barton [mailto:johnjbarton at google.com]

But the push scenario in your first paragraph would not use the cache either.

Yeah, that's what I was alluding to with the "most naïve" comment.

one or the other has to send its information at the outset of a import request, or

One way of doing this I came up with off the top of my head is to add some kind of "dependency graph version" or hash to the query string. I.e. <script type="module" src="entry.js?1234"></script>. The server can then assume that the client has in its cache version 1234 of the dependency graph, and can push the incremental updates since then (i.e. added or modified files). If parts of the cache were evicted, so that the versioning signal is not entirely accurate, then the penalty is not so bad, as you just fall back to the normal loading process for the evicted subset.

But I feel pretty silly speculating here as I'm not an expert on HTTP/2 techniques, and there are probably other methods that are better in various ways.

# John Barton (3 years ago)

On Thu, Apr 16, 2015 at 1:22 PM, Domenic Denicola <d at domenic.me> wrote:

From: John Barton [mailto:johnjbarton at google.com]

But the push scenario in your first paragraph would not use the cache either.

Yeah, that's what I was alluding to with the "most naïve" comment.

one or the other has to send its information at the outset of a import request, or

One way of doing this I came up with off the top of my head is to add some kind of "dependency graph version" or hash to the query string. I.e. <script type="module" src="entry.js?1234"></script>. The server can then assume that the client has in its cache version 1234 of the dependency graph, and can push the incremental updates since then (i.e. added or modified files). If parts of the cache were evicted, so that the versioning signal is not entirely accurate, then the penalty is not so bad, as you just fall back to the normal loading process for the evicted subset.

But I feel pretty silly speculating here as I'm not an expert on HTTP/2 techniques, and there are probably other methods that are better in various ways.

Perhaps, but I feel the issue is more fundamental. HTTP/2 shares statelessness with HTTP/1. It follows that the state of the client must be sent to the server or vice versa. HTTP/2 can make that process much faster but it's not going to know what state to send without instructions from clients or from servers. We can all make up those instructions one at a time and in our own unique ways or the module experts can come up with a good solution for the common cases. I'm hoping for the latter ;-)

jjb

# Glen (3 years ago)

You might find this interesting: ma.ttias.be/architecting-websites-http2-era/#comment-10935

(PUSH_PROMISE frame)

Glen.

# medikoo (3 years ago)

Thanks for clarifications,

Still after reading your comments I have a feeling that providing ES6 modules to browsers (efficient way) will be much more cumbersome and tricky than it is to provide CJS ones now. This may lead to scenario when most of us (for easy serve of bundle), will prefer to transpile them into something else, but I hope that won't be the case.

Another question raises about server support. People are relying on shared (or in cloud) hosting solutions. Do all popular servers (Apache, nginx, or http server in node.js) support HTTP/2 already? Is it easy to configure them to serve es6 modules efficient way?

-- View this message in context: mozilla.6506.n7.nabble.com/Fwd-Are-ES6-modules-in-browsers-going-to-get-loaded-level-by-level-tp337040p338232.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.

# Calvin Metcalf (3 years ago)

Neither node.js/iojs nor nginx. Though nginx supports spdy and there is a http2 module for node but it isn't compatible with express.

# John Barton (3 years ago)

On Thu, Apr 16, 2015 at 11:16 PM, medikoo <medikoo+mozilla.org at medikoo.com>

wrote:

Thanks for clarifications,

Still after reading your comments I have a feeling that providing ES6 modules to browsers (efficient way) will be much more cumbersome and tricky than it is to provide CJS ones now.

There is no technological reason to have such a feeling. The design of the ES6 module system makes creating bundles much easier and with much less chance of error. All of the imports can be computed from a given root module without relying on the developer build a list or organizing the bundle inputs into folders. This is not true for CJS.

jjb

# Matthew Phillips (2 years ago)

Can you clarify what you mean about bundling? Unless I've missed something, the ES6 module system does not have a story for bundling at all. Of course formats can be invented in userland but I'm not sure that they are any easier to implement than say AMD's. I might have missed something though, looking forward to your reply.

# Frankie Bagnardi (2 years ago)

Matthew, there are already tools for es6 modules + bundling (e.g. babel + webpack), or converting es6 modules to AMD (e.g. babel babeljs.io/docs/usage/modules).

# Eric B (2 years ago)

So just to clarify, when browsers support es6 modules we will still need some extra library to bundle the modules? This would mean es6 modules are only a syntactical addition and not something functional?

# Frankie Bagnardi (2 years ago)

In 10 years, we probably won't be using tools for the modules added in ES2015, but we might be using them for the changes made in ES2020.

# John Barton (2 years ago)

Correct, ES6 has no plans for a bundling solution and the whatwg group working on the loader has not proposed one.

Nevertheless bundling solution is easier to build and specify. In ES6, given a root module you can compute the (static) dependency graph as the basis for creating a bundle. The bundle will be complete and -- if the code has no unnecessary imports -- minimal. Moreover, the unnecessary imports can be determined by parser analysis alone.

Since bundling includes issues of transport, compression, and minification, I suspect that a standard may not emerge any time soon. Rather I expect a few tools to emerge and these will become de facto standards for bundling.

jjb

# Domenic Denicola (2 years ago)

Indeed, there is no built-in facility for bundling since as explained in this thread that will actually slow down your performance, and there’s no desire to include an antipattern in the language.

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Eric B Sent: Thursday, April 23, 2015 10:25 To: Frankie Bagnardi; Matthew Phillips Cc: es-discuss Subject: Re: Re: Are ES6 modules in browsers going to get loaded level-by-level?

So just to clarify, when browsers support es6 modules we will still need some extra library to bundle the modules? This would mean es6 modules are only a syntactical addition and not something functional?

On Thu, Apr 23, 2015 at 10:18 AM Frankie Bagnardi <f.bagnardi at gmail.com<mailto:f.bagnardi at gmail.com>> wrote:

Matthew, there are already tools for es6 modules + bundling (e.g. babel + webpack), or converting es6 modules to AMD (e.g. babelbabeljs.io/docs/usage/modules).

On Wed, Apr 22, 2015 at 7:10 PM, Matthew Phillips <matthew at bitovi.com<mailto:matthew at bitovi.com>> wrote:

Can you clarify what you mean about bundling? Unless I've missed something, the ES6 module system does not have a story for bundling at all. Of course formats can be invented in userland but I'm not sure that they are any easier to implement than say AMD's. I might have missed something though, looking forward to your reply.

# Erik Arvidsson (2 years ago)

To add one more option. You can create a service worker that loads a single zip file from the server and then splits it up for the client.

# James Burke (2 years ago)

On Thu, Apr 23, 2015 at 7:47 AM, Domenic Denicola <d at domenic.me> wrote:

Indeed, there is no built-in facility for bundling since as explained in this thread that will actually slow down your performance, and there’s no desire to include an antipattern in the language.

Some counterpoint:

For privileged/certified FirefoxOS apps, they are delivered as zip files right now. No HTTP involved. Asking for multiple files from these local packages was still slower than fetching one file with scripts bundled, due to slower IO on devices, so the certified apps in FirefoxOS right now still do bundling for speed concerns. No network in play, just file IO.

With service workers, it is hard to see that also being faster since the worker needs to be consulted for every request, so in that FirefoxOS app case, I would still want bundling.

With HTTP2, something still needs to do the same work as bundling, where it traces the dependencies and builds a graph so that all the modules in that graph can be sent back in the HTTP2 connection.

So the main complexity of bundling, a "build" step that traces dependencies and makes a graph, is still there. Might as well bundle them so that even when serving from browser cache it will be faster, see device IO concerns above.

Plus, bundling modules together can be more than just a speed concern: a library may want to use modules in separate files and then bundle them into one file for easier encapsulation/distribution.

I am sure the hope is that package managers may help for the distribution case, but this highlights another use related to bundling: encapsulation. Just like nested functions are allowed in the language, nested module definitions make sense long term. Both functions and modules are about reusing units of code. Ideally both could be nested.

I believe that is a bigger design hurdle to overcome and maybe that also made it harder for the module champions to consider any sort of bundling, but bundling really is a thing, and it is unfortunate it is not natively supported for ES modules.

The fun part about leaving this to transpilers is trying to emulate the mutable slots for import identifiers. I think it may work by replacing the identifiers with loader.get('id').exportName, or whatever the module meta/loader APIs might be, so having those APIs are even more important for a usable module system. There is probably more nuance to the transformation than that though. Like making sure to add in "use strict" to the function wrapper.

It is kind of sad that to use ES modules means to actually not really use them at runtime, to transpile back to ES5-level of code, and needing to ship a bootstrap loader script that allows slotting that the ES5-level code into the ES loader. For the extra script and transpiling concerns, it does not seem like an improvement over an existing ES5-based module systems.

James

# Brendan Eich (2 years ago)

James Burke wrote:

It is kind of sad that to use ES modules means to actually not really use them at runtime, to transpile back to ES5-level of code, and needing to ship a bootstrap loader script that allows slotting that the ES5-level code into the ES loader. For the extra script and transpiling concerns, it does not seem like an improvement over an existing ES5-based module systems.

Your lament poses a question that answers itself: in time, ES6 will be the base level, not ES3 or ES5. Then, the loader can be nativized. Complaining about this now seems churlish. :-|

# John Barton (2 years ago)

Sorry, but what I read was not an explanation but rather a hope that HTTP/2 would magically solve this problem. I'm all for HTTP/2 solving this. But so far I've not heard or read anything to back up the idea.

Will HTTP/2 make multiple round trips, one for each level of the dependency tree, competitive with pre-bundling? If not, then we will have to send dependency info to the client or cache info to the server or bundle. Or there is some magic as yet unexplained?

jjb

# Matthew Phillips (2 years ago)

I think the issue of round-trips is a red-herring. I spent some effort trying to optimize an es6 loader with caching in indexeddb and even that did not help much. I think what caridy said earlier is likely the biggest issue, processing a large number of Promises.

# Matthew Robb (2 years ago)

It would be great if the web app manifest included the dependency graph for the app. Something like the depCache in system js.

# James Burke (2 years ago)

On Thu, Apr 23, 2015 at 4:48 PM, Brendan Eich <brendan at mozilla.org> wrote:

Your lament poses a question that answers itself: in time, ES6 will be the base level, not ES3 or ES5. Then, the loader can be nativized. Complaining about this now seems churlish. :-|

So let's stay on this specific point: bundling will still be done even with ES modules and a loader that would natively understand ES modules in unbundled form. Hopefully the rest of my previous message gave enough data as to why.

If not natively supported in ES, it would be great to get a pointer to the officially blessed transform of an ES module body to something that can be bundled. Something that preserves the behaviors of the mutable slots, and allows using the module meta.

James

# Allen Wirfs-Brock (2 years ago)

On Apr 23, 2015, at 10:35 PM, James Burke wrote:

On Thu, Apr 23, 2015 at 4:48 PM, Brendan Eich <brendan at mozilla.org> wrote: Your lament poses a question that answers itself: in time, ES6 will be the base level, not ES3 or ES5. Then, the loader can be nativized. Complaining about this now seems churlish. :-|

So let's stay on this specific point: bundling will still be done even with ES modules and a loader that would natively understand ES modules in unbundled form. Hopefully the rest of my previous message gave enough data as to why.

If not natively supported in ES, it would be great to get a pointer to the officially blessed transform of an ES module body to something that can be bundled. Something that preserves the behaviors of the mutable slots, and allows using the module meta.

I think you're barking up the wrong tree. ECMAScript has never said anything about the external representation of scripts (called "Programs" prior to ES 2015) and the ES 2015 spec. doesn't impose any requirements upon the external representation of Modules. One Script or Module per external contain or multiple Scripts and Modules per external container - it makes no difference to the ES 2015 semantics.. Such encoding issues are entirely up to the host platform or ES implementation to define. But the platform/implementation has no choice in regard to the semantics of a Module (including mutability of slots or anything else in the ES 2015 specification). No matter a Module is externally stored it must conform to the ES 2015 module semantics to be a valid ES 2015 implementation.

So, if you want physical bundling, you need to convince the platform designers (eg, web, node, etc) to support that. Personally, I think a zip file makes a fine "bundle" and is something I would support if I was building a command-line level ES engine.

# James Burke (2 years ago)

On Fri, Apr 24, 2015 at 8:42 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>

wrote:

I think you're barking up the wrong tree. ECMAScript has never said anything about the external representation of scripts (called "Programs" prior to ES 2015) and the ES 2015 spec. doesn't impose any requirements upon the external representation of Modules. One Script or Module per external contain or multiple Scripts and Modules per external container - it makes no difference to the ES 2015 semantics.. Such encoding issues are entirely up to the host platform or ES implementation to define. But the platform/implementation has no choice in regard to the semantics of a Module (including mutability of slots or anything else in the ES 2015 specification). No matter a Module is externally stored it must conform to the ES 2015 module semantics to be a valid ES 2015 implementation.

Understood: the ES2015 spec makes it a point to not get into this. I was hoping that the module champions involved with the ES2015 spec would be on this list to respond to how to use modules in practice.

So perhaps I was incorrect to ask for "officially blessed", but more "a bundling form that module champions know will meet the ES2015 semantics of a Module".

The difficulty is precisely that ES2015 sets strong semantics on a Module that seem difficult to translate to a script form that could allow bundling.

I expect module meta to play a fairly important role for that translation, so having that defined, in some ES spec or elsewhere, and how that might work in bundling, would also be really helpful to complete the module picture.

So, if you want physical bundling, you need to convince the platform designers (eg, web, node, etc) to support that. Personally, I think a zip file makes a fine "bundle" and is something I would support if I was building a command-line level ES engine.

See my first post to this thread why when we had this in practice in FirefoxOS, a zip file with the contents, it was decided to use script bundling to increase performance. With the extensible web and more userland JS needed to bootstrap things like view selection and custom elements, getting the JS up and running as soon as possible is even more important.

The arguments so far against script bundling have been "there are better things that can be made for performance", but I do not see that in practice, particularly for the offline web on mobile devices. Besides that, I see modules as units of reusable code, like functions, which do allow bundling, nesting.

I can understand that is not the goal of ES2015, so hopefully the use case feedback will be useful to help flesh out a full module system that can use the ES module semantics.

James

# Brendan Eich (2 years ago)

James Burke wrote:

So let's stay on this specific point: bundling will still be done even with ES modules and a loader that would natively understand ES modules in unbundled form. Hopefully the rest of my previous message gave enough data as to why.

Not "bundling" in full; your previous post talked about HTTP2 but mixed dependency handling and bundling. You seemed not to advert to the problem of one big bundle being updated just to update one small member-of-bundle. One can be skeptical of HTTP2 but the promise is there to beat bundling.

So in a future where ES6 or above is baseline for web developers, and HTTP2 is old hat, there won't be the full bundling and module body desugaring you seem to be insisting we must have in perpetuity. (Yes, there will be dependency graphs expressed concisely -- that's not bundling.) Right?

# Jonathan Bond-Caron (2 years ago)

On Fri Apr 24 01:35 AM, James Burke wrote:

If not natively supported in ES, it would be great to get a pointer to the officially blessed transform of an ES module body to something that can be bundled. Something that preserves the behaviors of the mutable slots, and allows using the module meta.

Started using:

export in "name"; export with {bundle: "name"}; // with {metadata object}

disclaimer: Not officially blessed by spiritum consensum

# James Burke (2 years ago)

On Fri, Apr 24, 2015 at 11:39 AM, Brendan Eich <brendan at mozilla.org> wrote:

Not "bundling" in full; your previous post talked about HTTP2 but mixed dependency handling and bundling. You seemed not to advert to the problem of one big bundle being updated just to update one small member-of-bundle. One can be skeptical of HTTP2 but the promise is there to beat bundling.

So in a future where ES6 or above is baseline for web developers, and HTTP2 is old hat, there won't be the full bundling and module body desugaring you seem to be insisting we must have in perpetuity. (Yes, there will be dependency graphs expressed concisely -- that's not bundling.) Right?

There are some nice things with HTTP2 and being able to update a smaller set of files vs needing to change a bundle.

I am mostly concerned about startup performance primarily on mobile devices, and in the offline cases where HTTP2 is not part of the equation, at least not after first request. For the Firefox OS Gaia apps, they are currently zip files installed on the device. The same local disk profile exists with service worker-backed apps that work offline.

In the Firefox OS case, loading the bundle of modules performs better than not bundling, because multiple reads to local disk was slower than the one read to a bundled JS file. I expect this to be true in the future regardless of ES6 baseline or the existence of HTTP2.

A bundle of modules that have already been traced, usually ordered by least dependencies first, most dependencies last in one linearized fetch vs. in the unbundled case, the dependency tree needs to be discovered and then fetched as the modules are parsed.

It is hard to see the second one winning enough to discard wanting to bundle modules. Even if the bundle alternative is some sort of zip format that requires the whole thing to be available in memory. There is still the read, parse, back-and-forth traffic to the memory area, converting that to file responses. With service workers in play, it just adds to the delay.

James

# joe (2 years ago)

What I do is send the files over in as TAR archives, with mod_deflate turned on (they basically turn into .tar.gz files at that point). It's reasonably fast, even though I'm processing thirty megabytes of data this way (yay for typed arrays). I highly recommend it.

# joe (2 years ago)

Replies interspersed below

On Thu, Apr 23, 2015 at 9:48 AM, James Burke <jrburke at gmail.com> wrote:

On Thu, Apr 23, 2015 at 7:47 AM, Domenic Denicola <d at domenic.me> wrote:

Indeed, there is no built-in facility for bundling since as explained in this thread that will actually slow down your performance, and there’s no desire to include an antipattern in the language.

Some counterpoint:

For privileged/certified FirefoxOS apps, they are delivered as zip files right now. No HTTP involved. Asking for multiple files from these local packages was still slower than fetching one file with scripts bundled, due to slower IO on devices, so the certified apps in FirefoxOS right now still do bundling for speed concerns. No network in play, just file IO.

With service workers, it is hard to see that also being faster since the worker needs to be consulted for every request, so in that FirefoxOS app case, I would still want bundling.

If we're just talking about scripts, why not simply cache the entire zip file on the client end? That way there'd be only one request to the service worker (and perhaps queries to see if the zip's been updated).

With HTTP2, something still needs to do the same work as bundling, where it traces the dependencies and builds a graph so that all the modules in that graph can be sent back in the HTTP2 connection.

So the main complexity of bundling, a "build" step that traces dependencies and makes a graph, is still there. Might as well bundle them so that even when serving from browser cache it will be faster, see device IO concerns above.

There's one big advantage of not bundling: debugging tools. Chrome's debugger is much more stable than it used to be (I've not tried Firefox for a long time), to the point that being able to load one's scripts in their original form and map them to their location on the file system is quite nice (you can then live edit scripts in Chrome DevTools, which is unbelievably nice, you have no idea).

Plus, bundling modules together can be more than just a speed concern: a library may want to use modules in separate files and then bundle them into one file for easier encapsulation/distribution.

Right. Bundling libraries for release builds makes perfect sense.

I am sure the hope is that package managers may help for the distribution case, but this highlights another use related to bundling: encapsulation. Just like nested functions are allowed in the language, nested module definitions make sense long term. Both functions and modules are about reusing units of code. Ideally both could be nested.

I believe that is a bigger design hurdle to overcome and maybe that also made it harder for the module champions to consider any sort of bundling, but bundling really is a thing, and it is unfortunate it is not natively supported for ES modules.

The fun part about leaving this to transpilers is trying to emulate the mutable slots for import identifiers. I think it may work by replacing the identifiers with loader.get('id').exportName, or whatever the module meta/loader APIs might be, so having those APIs are even more important for a usable module system. There is probably more nuance to the transformation than that though. Like making sure to add in "use strict" to the function wrapper.

It is kind of sad that to use ES modules means to actually not really use them at runtime, to transpile back to ES5-level of code, and needing to ship a bootstrap loader script that allows slotting that the ES5-level code into the ES loader. For the extra script and transpiling concerns, it does not seem like an improvement over an existing ES5-based module systems.

James

Syntactically it's quite nice, though. IMHO, even if it's just syntactic sugar it's still worth it. I remember thinking the grammar was insane when I implemented it, but after using es6 modules for a while I now think they're (far) superior to even python's approach, at least in terms of usability.