Modules: execute deps, modify, execute (was Re: ES Modules: suggestions for improvement)

# James Burke (13 years ago)

On Wed, Jun 27, 2012 at 8:46 AM, Isaac Schlueter <i at izs.me> wrote:

Re: Conditional Importing

Only allowing import at the top level sounds like an ok idea, but I'm not so sure it's necessary.  Consider the current require() style:

if (some_rare_condition()) {  foo = require('foo') }

In requirejs and browserify the 'foo' module will be defined, but never loaded (ie, prefetched, evaluated for deps, bundled, etc).  In Node, it won't be read from the disk or evaluated (but if it's not there ON the disk, you'll have problems eventually, which is conceptually equivalent to having already been fetched, but without the pre-run safety check.)

Clarification for AMD loaders, like requirejs: 'foo' above will be fully defined in this case. In other words, it and its dependencies will have been fetched and evaluated before the module with that require('foo') call has been been executed (before its factory function has been run).

So require('foo') in AMD loaders just gives back the memoized module value. Conditional dependencies are handled either via callback-style require:

if(someRareCondition()) { require(['foo'], function(foo){}); }

or done via a loader plugin:

var foo = require('has!someRareTestName?foo');

For the browser this makes since because if it is a rare condition, the code should not even be shipped to the browser, but dynamically loaded. Of course build tools allow you inline foo if you think you might need it and do not want a dynamic network call later, and in that case, then foo is just in the optimized bundle but not executed/fully defined, until one of those code blocks ask for it.

This "execute dependencies before executing current module" behavior is the core of the "middle way" I tried to outline on the list before[1] and is also explained a bit in the most recent blog post[2].

I believe with it, it would allow more of a "run time" system that still gives enough "compile time" benefit to allow support for:

  • "import *" or future things like macros, without being a dynamic scope construct like "with".
  • allow easier use of existing js libraries that want to live in the both the old and new world by doing a runtime registration via a module API vs syntax.
  • since the fully exported value is available before the current module is executed, it could allow for deeper type checking over what the "statically check exports properties only" in the current proposal.

I have prototyped support for "import *" using this approach with the harmony-hm AMD loader plugin[3], so it is not something purely theoretical.

The discussion on what is allowed, in particular import *, could still happen, but at least there would be a baseline that would allow for them in a way that makes it easier for existing code to transition to the new world.

More info in the links below, but if it helps I can outline the model here in a fresh message:

[1] esdiscuss/2012-April/022098 [2] tagneto.blogspot.ca/2012/06/es-modules-suggestions-for-improvement.html [3] jrburke/require-hm

James

# John J Barton (13 years ago)

On Wed, Jun 27, 2012 at 9:47 AM, James Burke <jrburke at gmail.com> wrote:

The discussion on what is allowed, in particular import *, could still happen, but at least there would be a baseline that would allow for them in a way that makes it easier for existing code to transition to the new world.

I hope for a min/max module proposal to replicate the progress that the min/max class proposal produced. jjb

# Jussi Kalliokoski (13 years ago)

This brings up an interesting point about the modules, that being lazy loading. One appealing reason to use a module loader instead of just concatenating the scripts or using multiple script tags is that you can do feature detection and load polyfills for things you need instead of just forcing the client to download all the polyfills, regardless of whether they need them or not. Does the modules proposal attempt to solve this in any way?

# James Burke (13 years ago)

On Wed, Jun 27, 2012 at 11:40 AM, Jussi Kalliokoski <jussi.kalliokoski at gmail.com> wrote:

This brings up an interesting point about the modules, that being lazy loading. One appealing reason to use a module loader instead of just concatenating the scripts or using multiple script tags is that you can do feature detection and load polyfills for things you need instead of just forcing the client to download all the polyfills, regardless of whether they need them or not. Does the modules proposal attempt to solve this in any way?

You may be able construct something with the Module Loaders API, but nothing by default, so it would mean shipping a library to enable it. I prefer built in support for loader plugins a la AMD though.

If you want to explore that further, I suggest starting a different thread. I prefer this thread to be very targeted on the eval/modify/eval approach. The code examples I had in my original message were to give context on that approach.

James

# David Herman (13 years ago)

On Jun 27, 2012, at 11:40 AM, Jussi Kalliokoski wrote:

This brings up an interesting point about the modules, that being lazy loading. One appealing reason to use a module loader instead of just concatenating the scripts or using multiple script tags is that you can do feature detection and load polyfills for things you need instead of just forcing the client to download all the polyfills, regardless of whether they need them or not. Does the modules proposal attempt to solve this in any way?

System.load gives you dynamic loading.