3

The ES6 module system seems to be a proper fit for unifying the CommonJs / AMD syntaxes. As a requireJs/AMD-user I'd like to convert to ES6 modules (using babel.js for now).

There seems to be one problem though; reading through the docs and tutorials, there doesn't seem to be possible to load module packages that are dependendent on more than one baseurl. Using requireJs this is solvable using the context field:

// async dependencies are loaded from http://path/to/domain
var contextedRequire1 = require.config({
  baseUrl: 'http://path/to/domain/js',
  context: 'mainContext'
});    

// async dependencies are located on http://path/to/otherdomain
var contextRequire2 = require.config({
  baseUrl: 'http://path/to/otherdomain/js',
  context: 'pluginContext'
});

contextedRequire1(['main.js'], function(main){
  // loaded using http://path/to/domain/js/main.js
  contextedRequire2(['plugin-lazyloading-deps.js'], function(plugin){
    plugin.init();
  });
});

In main.js

define(['main-deps'], function(mainDeps){
  // loaded using http://path/to/domain/js/main-deps.js
})

In plugin-lazyloading-deps.js

define(['require'], function(require){
  // loaded using http://path/to/otherdomain/js/plugin-lazyloading-deps.js
  if(Modernizr.touch) {
    require(['hammer'], function(){
      // loaded using http://path/to/otherdomain/js/hammer.js
      hammer.init();
    })
  }
})

In ES6 async module imports this isn't possible, since System is a singleton

System.baseURL = "http://path/to/domain/js";
System.import("main").then(function(main){
  // loaded using http://path/to/domain/js/main.js

  // This will potentially break when main.js tries to load hammer.js from http://path/to/domain/js
  System.baseURL = "http://path/to/otherdomain/js";
  System.import("plugin-lazyloading-deps").then(function(){ /** code **/ });
});

My question is: Is there something in the docs that I've missed (possible to subclass System to be able to config several baseUrls), or is this something in the works for future module extensions?

Aksel N.
  • 67
  • 1
  • 8
  • The use case for loading packages of async modules from different domains, are when several teams are creating sub-apps within a large site (main app) - that needs to be built and deployed on different domains without the main app being re-deployed. – Aksel N. May 31 '15 at 09:41

2 Answers2

1

At least with the current version of SystemJS, you can provide wildcard paths. https://github.com/systemjs/systemjs/wiki/Configuration-Options#paths-unstable

I haven't used it myself, but for your case, seems you'd do

System.baseURL = 'http://path/to/domain/js';
System.paths['plugin-*'] = 'http://path/to/otherdomain/js/plugin-*';
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • Thanks, not quite what I was looking for, but nice to see that path wildcards are better functioning than within requireJs. – Aksel N. Jun 01 '15 at 07:06
1

It seems as if System.js has an (undocumented) way - by extending the System object using Object.create(System).

var context1 = Object.create(System);
context1.baseURL = 'http://path/to/otherdomain/js';
context1.import('plugin-lazyloading-deps').then(function(m){
  m.setSystem(context1);
  m.initialize();
));

Please note that until the System object is implemented in browsers/nodeJs, this approach may break. Hopefully though, the same effect may be achievable using class context1 extends System in ES6.

The implementation is not 100% analogous to requireJs, since it's not possible to inject the current context to async-load other modules from within a scoped context (ie. the 'require'-dependency needs to be replaced with m.setSystem(..)or similar).

Aksel N.
  • 67
  • 1
  • 8