<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jul 2, 2014 at 1:09 AM, Jussi Kalliokoski <span dir="ltr"><<a href="mailto:jussi.kalliokoski@gmail.com" target="_blank">jussi.kalliokoski@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div class="h5">On Tue, Jul 1, 2014 at 10:28 PM, Kevin Smith <span dir="ltr"><<a href="mailto:zenparsing@gmail.com" target="_blank">zenparsing@gmail.com</a>></span> wrote:<br>
</div></div><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5">

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">

<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div>As such, we are balancing the marginal user experience gains of "export-overwriting" against the better support for circular dependencies of "real" modules.<br></div></div></div></div></blockquote>



<div><br></div></div><div>Another way of looking at it:</div><div><br></div><div>Being in control of the language, you can always invent new sugar to optimize user experience (within limits) when real usage data proves its worth.  But the core model can't be changed.</div>



<div><br></div><div>As such, it seems like it would be better to err on the side of making the core model simple and solid, leaving minor UX optimizations to future syntax.</div></div></div></div></blockquote></div></div>
<div><br>But it's neither simple nor solid. It's overtly complicated to support features that shouldn't be there.<br></div></div></div></div></blockquote><div><br></div><div>Actually I think you have missed important features that the current proposal supports and are needed for your use cases.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div>

<br></div><div>Sorry in advance for the tone of this message, it is quite negative. But the intent is constructive. To me modules are the most anticipated feature in ES6 and I've been closely following the discussion and the proposal's evolution and I've been extremely thrilled. Finally we could have a chance of alleviating the situation of having a ton of non-intercompatible different module loaders. I haven't contributed much to the discussion since I liked the overall direction. However, now that I've been actually using the modules for a while with a couple of different transpilers, it's become obvious that the design is inherently broken (not the fault of the transpilers, they are actually probably better in some aspects than the real thing), and in order for ES modules to help the situation instead of making it worse, it needs to be better than the existing solutions.<br>


<br></div><div>The core unique selling points of ES6 modules as opposed to the other module loading systems:<br><br></div><div>* Language built-in: the strongest point. This makes sure that most tooling should support the feature out of the box and that module authors are more inclined to provide their modules in this format. But the design can be whatever and this point will still hold true, so no points to the design here.<br>


</div><div>* (Reliably) statically analyzable syntax. This is my favourite feature and really awesome. Allows engine to fetch next modules while the current one is still being parsed, </div></div></div></div></blockquote>
<div><br></div><div><div>This isn't true -- all module designs in play require parsing (include of course CJS and AMD).</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>and tooling to better understand what the code does. However, this would hold true even if all we standardized was syntactic sugar on top of requirejs.<br>
</div></div></div></div></blockquote><div><br></div><div>I don't believe that anyone expects such an outcome.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>

</div><div>* Cyclic dependencies: First of all, this is not a feature you want to necessarily encourage. It looks good in academia, but in my career I've yet to see real world code that would benefit more from cyclic dependencies more than refactoring. Not to mention that having cyclic dependencies have been possible in global scope modules since LiveScript, and is possible in CommonJS as well if you do a little DI: <a href="https://gist.github.com/jussi-kalliokoski/50cc79951a59945c17a2" target="_blank">https://gist.github.com/jussi-kalliokoski/50cc79951a59945c17a2</a> (I had such a hard time coming up with an example that could use cyclic dependencies that I had to dig the example from modules examples wiki). And honestly I don't think it's a feature that deserves to be easier to do than my example, and especially not worth making other design compromises for.<br>
</div></div></div></div></blockquote><div><br></div><div>The arguments for and against supporting cyclic dependencies seem to be academic. I'm yet to see any evidence of their importance in practice nor proof they they are fundamental ... or not. </div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div>
</div><div>* Mutable bindings: This will make a good chapter in a future edition of JavaScript: The bad parts, along with being able to redefine undefined. You can have mutable bindings in other module systems as well, just reassign something in your exports and then your consumer uses the exports property directly. A lot of WTFs avoided and even doing it like that will ring alarm bells in code review.<br>

</div><div>* Compile-time errors: This not a feature, it's a bug. Try finding a website that doesn't somewhere in its code check for whether you have a feature / module available, i.e. optional dependencies. Some examples: Angular has jQuery as an optional dependency; spritesheet generator modules for node that have multiple engines as optional dependencies because some of them may be native modules that don't compile on all platforms. Also things get worse if platform features are implemented as modules. Let's say things like localStorage, IndexedDB and friends were provided as modules and as a result, things like localforage would either not exist or would be infinitely more complex. Just look at github search for keywords `try` and `require` <a href="https://github.com/search?l=javascript&q=try+require&ref=cmdform&type=Code" target="_blank">https://github.com/search?l=javascript&q=try+require&ref=cmdform&type=Code</a> to see how widely used the pattern of wrapping a module load in a try-catch is.<br>
</div></div></div></div></blockquote><div><br></div><div>Optional dependency is completely supported by Loader.import().  Furthermore its promise based API avoids try/catch goop.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>
<br></div><div>Now let's look at some things that tip the odds into existing solutions favor:<br><br></div><div>* Massive amount of existing modules.<br></div><div>* Existing large-scale user-bases.<br></div><div>* Node has stated that the core will always be CommonJS, meaning that on node, in order to use ES6 modules, you'll have to be using two different module systems which doesn't sound like a thing that people would do unless there's proven benefits.<br>
</div></div></div></div></blockquote><div><br></div><div>These points are not relevant since nothing in the current design prevents these success stories from continuing.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>
</div><div>* Completely dynamic. </div></div></div></div></blockquote><div><br></div><div>Neither Common JS nor AMD modules are not complete dynamic.  Both systems rely on preprocessing JS to package modules for browsers. </div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div>Now, I know there are people that think that this isn't not good, but it is. It gives you a lot of power when debugging things or playing around with new things (something I haven't seen discussed re:modules on this list). One of the greatest things in JS is that instead of reading the usually poor documentation, let alone the code, of something you want to use you can just load it up in node or the developer tools and play around with it. With node, you require() something in the repl and you see immediately what it exports. </div>
</div></div></div></blockquote><div><br></div><div>Loader.get() provides the module.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>You can do whatever with the exports: enumerate, extend your own exports with them, whatever you want, it's just an object. </div></div></div></div>
</blockquote><div><br></div><div>As far as I understand it, the return value from Loader.get() is also an object.  The mutable bindings are not mutable after import: they are  just properties.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>In debugging situations and learning of new libraries, it's really straightforward to just require the module and give it different inputs to see what the outputs to see if it's something you want to use or what's the edge case of the method that causes the bug you're trying to fix (and then just make a failing test out of it). I can't tell you how many times a day I write angular.element(document.body).injector().get("Something") or require(function (Something) { window.Something = Something }) in the dev tools. </div>
</div></div></div></blockquote><div><br></div><div>IMO, poor support for modules in devtools is a consequence of delay in the ES process for modules.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>With the current design of ES6 modules, I don't think it's even feasible to allow the users to type into the devtools console first `import something from "somewhere"` and then in the next entry refer to `something`. </div>
</div></div></div></blockquote><div><br></div><div>Loader.import() provides this ability.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Not to mention that the dynamic loading in the existing solutions caters for situations like build tools, for example loading grunt tasks. The case there is that a lot of grunt plugins have dependencies lists from here to the end of the world, so when you run a task, you only want to load the modules that are required by that task to avoid concatenating files taking 20 seconds because it loads a ton of crap for other tasks. So people started loading the modules when the tasks get called, not all at the same time when initializing and this proved to have significant performance benefits. So much that now there's jit-grunt that by guessing and configuration is able to load the modules for a given task when the given task is invoked. This is simply not possible with ES6 modules without a massive boilerplate spaghetti with async stuff.<br>
</div></div></div></div></blockquote><div><br></div><div>Badly designed systems will exist independent of language features. The combination of statically analyzed declarative imports and dynamic imperative import allows much better tool support than is possible with Common JS and AMD. </div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div>
<br></div><div>Given all this, how are we supposed to convince people to use this stuff? These concerns are not something that can be fixed later either, they're fundamental to the current design.<br></div></div></div>
</div></blockquote><div><br></div><div>I think that you are misunderstanding the current design. I do agree that devtools support is very important. Sadly this support is not given enough weight. We warned about the issue with exceptions in Promises and now we have Promises that easily make programs essentially undebuggable. Modules are less fundamentally broken, but they have more surface area for tools to cover. </div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div></div><div><br></div>
<div>Now I can guess you're thinking that this was purely destructive, so where's the constructive part? The key takeaway is that I'm no longer sure that we should even try to ship modules with ES6. On the web platform, it's better to not hurry shipping something that's just going to end up on the wall of shame of short-sighted decisions. Brendan probably knows this the best. :) Let's take the time to actually ship something that we can confidently say is better than the status quo rather than doing this: <a href="http://xkcd.com/927/" target="_blank">http://xkcd.com/927/</a></div>
</div></div></div></blockquote><div><br></div><div>This commonly cited comic is both true and not a sign of problems: progress is in fact N+1 standards.  That's they way human interaction works.</div><div>jjb</div></div>
</div></div>