By Oleksii Rudenko May 5, 2015 7:55 PM
Notes About Differences in Plugin Micro Syntax Between Various ES6 Module Loaders

I’ve made a small research on how various module loaders handle non-js resources and template(hbs) files in particular. I’ve compared three of them: Webpack, AMD/RequireJS, the one JSPM relies on and the one ember-cli uses.

For example, in JSPM one may use plugins to load and compile templates:

import tmpl from './my-tmpl.hbs!';

And it’s not good because this code can be used only with JSPM. Here are some examples demonstrating the syntax which other loaders support:

  • ember-cli:
import tmpl from './my-tmpl';
  • Webpack:
import tmpl from '!hbs./my-tmpl.hbs';
  • AMD/requireJS:
import tmpl from 'hbs!./my-tmpl.hbs';

As you can see, all of them use similar but not exactly the same syntax because it is not a standard yet and no standardization is going on at the moment.

Also you may have noticed that ember-cli actually omits any plugin information and works with templates like with any other JS module. That is achieved by the convention over configuration approach and ember-cli’s loader actually does not support plugins. As part of its build process, ember-cli compiles all templates, strips off extensions and exposes templates as normal JS files. This is done for all templates within any directory that is called templates. So the aforementioned example in reality looks this:

import tmpl from './templates/my-tmpl'

What is also interesting is that webpack is more flexible with regards to the plugin syntax and supports import declarations of the following type import tmpl from './my-tmpl.hbs'. So it requires only the extension w/o the exclamation mark or any other additions in order to understand how the module should be loaded. Of course, additional configuration is required for this to work but it does not modify the source code. Support for this kind of configuration is hopefully coming to JSPM soon: issue on Github.

Alternatively, as Guy Bedford pointed out, one can implement such configuration himself:

var systemNormalize = System.normalize;
System.normalize = function(name, parentName) {
  if (name.match(/\.jsx$/))   // check your conventions
    name = name + '!';        // if matches define which plugin to use
  return systemNormalize.call(this, name, parentName);
}

Learn how to make System.normalize hook work with build/buildSFX commands in the next post.

Thanks for reading.