Framework: export default prevents CustomElement from working

Created on 19 Feb 2017  路  6Comments  路  Source: aurelia/framework

I'm submitting a bug report

  • Library Version:
    1.0.8

Please tell us about your environment:

  • Operating System:
    OSX 10.12.3
  • Node Version:
    6.9.1

  • NPM Version:
    3.10.8

  • JSPM OR Webpack AND Version
    webpack 2.2.1

  • Browser:
    all

  • Language:
    ESNext

Current behavior:
When creating a view-model (.js) file for a CustomElement, using export default class ... results in Aurelia failing silently when placing the component on a view. There are no errors, but the custom element is not inserted. Changing the syntax to export class ... fixes the problem.

Expected/desired behavior:
The most common case for view-model files seems to be to export a single class, the view-model class. Best practice from e.g. airbnb eslint rules suggest that making a default export when there is only one export is the appropriate way to go. In any case, it should not fail silently, it should either provide a warning that default exports are not supported for custom element view models, or it should work.

question

All 6 comments

The reason is that your element is named default, which is probably not what you expect. The convention uses the export name. Try adding a @customElement('name-here') decorator to specify the name if you want to use default exports.

@EisenbergEffect that's not the correct behavior, though. This is definitely a bug, not a question, and it should be reopened as such. The syntax export default <classname> is accepted part of the ES6 spec (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export), so I don't see why that's valid logic to take the keyword default and assume it's the name of the module.

The name of the default export is default. When Aurelia inspects the module, that is the name it gets default. The default exportcan be though of as just another named export, with the name of default. Even if you do export default class Foo, Foo goes away. If you don't believe me, let me show you.

I created a module for a StackOverflow question recently. I called the module alert. I've modified it for this example and added a second, named export MyUselessValueConverter. Here is the code for the module:

import {bindable} from 'aurelia-framework';

export default class Alert {
  @bindable type = 'default'
}

export class MyUselessValueConverter {
  toView(value) {
    return value;
  }
}

When I inspect the ES2015 module, as transpiled by Babel and then imported using, in this case, RequireJS, this is what I see:
image

Aurelia is using its conventions when inspecting the module. The convention is to used the export's name for the component's name. In this case, the export's name is default, and so Aurelia determines that the name of the custom element will be <default></default>.

As @EisenbergEffect mentioned, you can override the convention by using the @customElement decorator, or the appropriate decorator for the type of component you wish to create.

That being said, @EisenbergEffect maybe we could add special processing to check the name property of a default export when determining the component name? I'm not sure if the name property is part of the standard or is just an artifact of tranpilation.

@AshleyGrant I appreciate the detailed explanation. Given that default has been a reserved word in ECMAScript for quite a while now, it seems like having the Aurelia framework add a check and then handle the case differently would make sense to me. In the meantime, obviously, I can use the work-around.

@pvencill I tried to read the spec to see if the name property is standard, but I had to move on with my day after a few minutes. You might have time to check here: http://www.ecma-international.org/ecma-262/6.0/

The name is a standard property of function/constructor but we can't use that because minifiers usually change the name during the minification process. Using that would mean that your code would work during dev and test but completely break with no errors in production. The export name is part of the official API contract and doesn't change, so it's the only safe thing we can use, besided the explicit decorator.

Was this page helpful?
0 / 5 - 0 ratings