1

I am converting some code to ES6 syntax using JSPM/SystemJS/BabelJS.

I have the following:

// main.js:
console.log('foo');
import * as Backbone from 'backbone';
import * as Cocktail from 'backbone.cocktail';
Cocktail.patch(Backbone);
console.log('bar');

import Application from 'background/application';
console.log('application:', Application);

// application.js:
console.log('baz');
export default {};

This code outputs baz foo bar application: {}.

I would like to output: foo bar baz application: {} such that Cocktail.patch is ran before any code in application.js

I am able to achieve this by re-writing my code as:

// main.js:
console.log('foo');
import * as Backbone from 'backbone';
import * as Cocktail from 'backbone.cocktail';
Cocktail.patch(Backbone);
console.log('bar');

System.import('background/application').then(function(Application){
    console.log('application:', Application.default);
});

// application.js:
console.log('baz');
export default {};

However, this feels convoluted and incorrect. It's leveraging SystemJS explicitly rather than ES6 import/export syntax. How can I wait before parsing application.js using ES6 syntax?

Sean Anderson
  • 27,963
  • 30
  • 126
  • 237
  • 1
    Not that you can do much with it ATM, but know that the ES6 Module Loader draft that SystemJS implements (through the polyfill) was removed from the specification, and is being replaced by [`loader`](https://github.com/whatwg/loader) – Amit Aug 26 '15 at 21:46

2 Answers2

3

import is not actually an expression, it is just mark for compiler, which modules should be imported before this code will run. This is similar to how var definition works. All variables is defined before all expressions in that scope, this is named variable hoisting.

So if you want to be sure, that your code will run before imports, you can move it into separate module

// setup.js
console.log('foo');

// backbone-patch.js
import * as Backbone from 'backbone';
import * as Cocktail from 'backbone.cocktail';
Cocktail.patch(Backbone);
console.log('bar');

// application.js:
console.log('baz');
export default {};

// main.js:
import './setup';
import './backbone-patch'
import Application from './application';
console.log('application:', Application);

Imports will be loaded in order of appearance and you will get the desired result

Community
  • 1
  • 1
just-boris
  • 9,468
  • 5
  • 48
  • 84
2

ES2015 (AKA ES6) imports are statically analyzed. They are not executed in the standard flow of a JavaScript code, but are rather analyzed and executed before any of the importing code is executed.

Using System.import makes the import "dynamic" and occur at runtime, thus allowing you to control the actual timing / order of events.

Amit
  • 45,440
  • 9
  • 78
  • 110
  • 1
    How is one able to shim functionality into a module before other dependencies use that module with ES6 imports? Is that not supported? – Sean Anderson Aug 26 '15 at 21:37
  • Considering the basic idea of modules, and keeping global namespace clean, it shouldn't matter to any dependencies what happens inside an imported module, nor should the order of event matter. An importing code should only care that the imported objects are available to use. – Amit Aug 26 '15 at 21:39
  • In a scenario I faced when working with dygraphs, which DOES "pollute" the global namespace, I resorted to using multiple, chained System.import calls to control the order. – Amit Aug 26 '15 at 21:40
  • Interesting. The reasoning does make sense, but still leaves me feeling a bit weird. If I want to extend the functionality of a third-party library. For instance, mixing additional functionality into lodash through _.mixin, I would need to create a module (i.e. "extendedLodash") and have all dependencies import extendedLodash... rather than modifying lodash itself and having other modules receive those modifications explicitly? I guess that makes sense from a purity standpoint, but a bit inconvenient. – Sean Anderson Aug 26 '15 at 21:47
  • I didn't follow your "extendedLodash" scenario, but just so you know, lodash happens to be one of the libraries that DID make the leap to [ES Modules](https://github.com/lodash/lodash/tree/3.10.1-es#lodash-es-v3101) – Amit Aug 26 '15 at 21:51