Framework: Potential unintended inconsistency between plugin and feature

Created on 1 Sep 2015  路  10Comments  路  Source: aurelia/framework

When a plugin has an index.js and a myClass.js file and the index.js has following code:

export {MyClass} from './myClass';
export function configure(aurelia, configCallback){
};

MyClass can be consumed as follows:

import {MyClass} from 'myPlugin;

When using exactly the same configuration, but as a feature, the consumption of myClass needs to be more specific

import {MyClass} from 'myFeature/myClass';

Is this 'by design' or just a bug :)

Most helpful comment

I understand, but my point is that the way how an actual import is done differs between a plugin and a feature.
For a plugin: import {MyClass} from 'myPlugin';
For a feature: import {MyClass} from 'myFeature/myClass';
In both example MyClass is re-exported explicitely in the index.js.

The reason why I think it can become important is that people will tend to do initial plugin development under the form of a feature and then later on 'package' things as plugin.

All 10 comments

It's a consequence of how the ES6 module system works. The plugin usually re-exports all its modules via its index.js file, so you can import all exported values from there. if you are writing a feature, you can make it work the same way by also re-exporting values, but I don't really recommend the extra work.

I understand, but my point is that the way how an actual import is done differs between a plugin and a feature.
For a plugin: import {MyClass} from 'myPlugin';
For a feature: import {MyClass} from 'myFeature/myClass';
In both example MyClass is re-exported explicitely in the index.js.

The reason why I think it can become important is that people will tend to do initial plugin development under the form of a feature and then later on 'package' things as plugin.

It has to do with the way it is configured with system.js. If you map paths to the plugins index file then it will work identically for both.

Sorry for bothering you again Rob.
Ok, maybe I'm misunderstanding the usage of plugins.
My feature folder (myFeature) is just a subfolder of /src and I register it as follows:

aurelia.use.feature('myFeature');

Obviously, in contract with a feature, a plugin has a registration in config.js.
Are you suggesting that a feature needs also registration in config.js ?
With the above way of working, the feature works in runtime, but I'm getting problems while running tests with karma.

When you jspm install a plugin, jspm adds an entry in the config.js that allows it to look up the main module for that plugin. Usually a plugin exposes its entire api through that single module.

A feature could also do this. The feature's index would need to import and re-export all the classes contained in that feature. If this is done, then any of them can be accessed through the main module "feature/index". You could also add a mapping in your config.js so that "feature" would point to "feature/index" then you would be able to import anything from that feature via "feature".

This actually isn't something having to do with aurelia, but rather how ES6 modules work in conjunction with a loader like system.js that supports map and path config.

Thanks Rob.
While the 'use case' for a plugin is very clear, that's, for me, not the case for a 'feature'.
a) why not simply storing the different modules of an app in ordinary folders (in /src) instead. I miss then the config callback (what a feature would give me), but the added value of this is larger for a plugin than for a feature.
b) adding mappings manually in config.js. In my understanding config.js is, at least for the 'variable' parts, under control of jspm (just like package.json is managed by npm).
Anyhow, I'm feeling that this is here not the good place to discuss this. I'll ask more opinions on gitter.
Take care

I managed to get local plugins work with the following configuration:

In config.js:

System.config({
  // ... options
  paths: {
    "*": "dist/*",
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*"
  },
  map: {
    "localPlugin": "path/to/localPlugin/index"
    // ... other mappings
  }
}

In main.js:

export function configure(aurelia) {
  aurelia.use.plugin('localPlugin');
  // ...
}

Then in all modules:

import {Foo, Bar} from 'localPlugin';

Obviously Foo and Bar must be exported in dist/features/localPlugin/index.js.

Hi Giovanni,

Yeah, that's what I did as well, more or less, and it works but it breakes the unit tests.
May I presume that your plugin is somewhere under the /src folder ?
I map without /index !

Try as a basic sample, starting from skeleton- to create a feature that contains all .html/js except for main and app:

image

When running than the unit tests, things go wrong:

Chrome 45.0.2454 (Windows 10 0.0.0) ERROR: 'Potentially unhandled rejection [5] Error: XHR error (404 Not Found) loading http://localhost:9876/base/MyFeature/child-router.js
    at error (http://localhost:9876/base/jspm_packages/system.src.js?662c5eaab59718da347a899ec3dc1239f458b2c2:1028:16)
    at XMLHttpRequest.xhr.onreadystatechange (http://localhost:9876/base/jspm_packages/system.src.js?662c5eaab59718da347a899ec3dc1239f458b2c2:1036:13)'

Obviously, I export e.g. child-router in index.js of the feature) and import it in the unit test:

import {ChildRouter} from 'MyFeature/child-router';

I have really not the feeling I'm developing an 'application component' when using the feature functionality.

Cheers and thanks for the feedback.

How do we "map paths to the plugins index file" when using the aurelia-cli? We appear to no longer have a config.js file, and instead have an aurelia.json file. In what property of the aurelia.json do we map the path to the plugins index file? The loader.plugins property looks promising. Note that, since we're using TypeScript, pointing to the index.ts file seems to fail, because it isn't JavaScript yet.

This works tidily.

    "bundles": [
      {
        "name": "my-bundle.js",
        "source": [
          "**/src/my-plugin/*.{js,html}"
        ],
        "dependencies": [
          {
            "name": "my-plugin",
            "path": "../src/my-plugin", 
            "main": "index"
          }
        ]
      },
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gbreeze picture gbreeze  路  4Comments

txels picture txels  路  6Comments

FunkMonkey33 picture FunkMonkey33  路  5Comments

dasch88 picture dasch88  路  4Comments

piet-v picture piet-v  路  3Comments