Unable to use Aurelia plugin

2019-05-22 15:27发布

I'm trying to move one of my custom elements into a plug-in so that I can re-use it across projects.

I had a look at the skeleton plugin and noticed that it has a src/index.js that returns a config with all custom elements defined as globalResources.

So I tried the same thing and I basically have:

src/index.js

export function configure (config) {
    config.globalResources([
        './google-map',
        './google-map-location-picker',
        './google-map-autocomplete'
    ]);
}

And then I have each one of my custom elements next to index.js, for example:

google-map.js

import {inject, bindable, bindingMode, inlineView} from 'aurelia-framework';

@inlineView(`
    <template>
        <div class="google-map"></div>
    </template>
`)
@inject(Element)
export class GoogleMapCustomElement {
    // All the Custom Element code here
}

I've also set up a basic npm script that runs babel on the code and sticks it in dist/:

"main": "dist/index.js",
"babel": {
  "sourceMap": true,
  "moduleIds": false,
  "comments": false,
  "compact": false,
  "code": true,
  "presets": [ "es2015-loose", "stage-1"],
  "plugins": [
    "syntax-flow",
    "transform-decorators-legacy",
    "transform-flow-strip-types"
  ]
},
"scripts": {
  "build": "babel src -d dist"
},

Tbh I'm not entirely sure this is all correct but I took some of it from the skeleton plugin and it seems to run fine.

Anyway, the problem I'm having is that after I install the plugin (npm install --save-dev powerbuoy/AureliaGoogleMaps), add it to my aurelia.json in build.bundles[vendor-bundle.js].dependencies and tell aurelia to use it in main.js (.use.plugin('aurelia-google-maps')) I get:

GET http://localhost:9000/node_modules/aurelia-google-maps/dist/index/google-map.js (404)

So my question is, where does it get the dist/index/ part from?? I'm configuring my globalResources in index.js but nowhere does it say that I have an index folder.

What am I doing wrong?

Bonus question: What is the bare minimum required to transpile my ES6 plug-in code so that others can use it? Does my babel configuration look correct?

3条回答
你好瞎i
2楼-- · 2019-05-22 16:06

What about referencing your plugin within aurelia.json, like this:

{
  "name": "aurelia-google-maps",
  "path": "../node_modules/aurelia-google-maps/dist",
  "main": "index"
}
查看更多
家丑人穷心不美
3楼-- · 2019-05-22 16:06

Update:

Edit: thanks for clarifying why you don't want to use the whole skeleton-plugin package.

Focusing on your original question: aurelia-cli uses RequireJS (AMD format) to load dependencies. Probably, your current output has a different format.

Add transform-es2015-modules-amd to babel.plugins to ensure AMD-style output, so it will be compatible with RequireJS and therefore with aurelia-cli.

"babel": {
"sourceMap": true,
"moduleIds": false,
"comments": false,
"compact": false,
"code": true,
"presets": [ "es2015-loose", "stage-1"],
"plugins": [
        "syntax-flow",
        "transform-decorators-legacy",
        "transform-flow-strip-types",
        "transform-es2015-modules-amd"
    ]
}

Original:

There are several blog post about plugin creation, I started with this: http://patrickwalters.net/making-out-first-plugin/ .

Of course, there have been many changes since then, but it's a useful piece of information and most of it still applies.

I'd recommend using plugin-skeleton as project structure. It provides you with a working set of gulp, babel, multiple output formats out-of-the-box. With this approach, your plugin's availability wouldn't be limited to JSPM or CLI only but everyone would have the possibility to install it regardless of their build systems.

Migration is fairly easy in your case:

  • Download skeleton-plugin
  • Copy your classes + index.js into src/
  • npm install
  • ...wait for it...
  • gulp build
  • check dist/ folder
  • most of your pain should now be gone :)

Here are some details based on my observations/experience.

1. Main index.js/plugin-name.js:

In general, a main/entry point is required, where the plugin's configure() method is placed. It serves as a starting point when using it within an Aurelia application. This file could have any name, usually it's index.js or plugin-name.js (e.g. aurelia-google-maps.js) to make it clear for other developers what should be included for bundling. Set that same entry point in package.json as well.

In addition to globalResources, you can implement a callback function to allow configuration overrides. That can be called in the application, which will use the plugin. Example solution

Plugin's index.js

export * from './some-element';

export function configure(config, callback) {
    // default apiKey
    let pluginConfig = Container.instance.get(CustomConfigClass);
    pluginConfig.apiKey = '01010101';

    // here comes an override
    if (callback) {
        callback(pluginConfig);
    }

    ...

    config.globalResources(
        './some-element'
    );  
}

Your app's main.js

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging()
    .plugin('aurelia-google-maps', (pluginConfig) => {
        // custom apiKey
        pluginConfig.apiKey = '12345678';
    });

  aurelia.start().then(a => a.setRoot());
}

2. HTML and CSS resources:

  • If you have html only custom elements, you can make them available using globalResources.
  • Custom css styling is going to require a bit of additional configuration in bundling configuration (see below).

3. Using the plugin with aurelia-cli: Documentation

One of the first new features you'll see soon is a command to help you with 3rd party module configuration. The command will inspect a previously npm-installed package, and make a configuration recommendation to you, automating the process if you desire.

While we are looking forward to that above moment, let's edit aurelia.json:

  • Configure plugin dependencies. If there are any external libraries (e.g. Bootstrap), then those should be included before your plugin.
  • Include your plugin:
...
{
    "name": "plugin-name",
    "path": "../node_modules/plugin-name/dist/amd",
    "main": "plugin-name",
    "resources": ["**/*.html", "**/*.css"]  // if there is any
},
...

Now, your plugin is ready to include it in main.js as showed in Section 1..

I hope you didn't get sick of reading the word 'plugin' so many (21!) times. :D

查看更多
一纸荒年 Trace。
4楼-- · 2019-05-22 16:18

I have absolutely no idea why, but in order to solve this problem I actually had to move my custom elements inside an index/ folder.

So now I have this:

- index.js
- index/
    - custom-element-one.js
    - custom-element-two.js

And my index.js still looks like this:

export function configure (config) {
    config.globalResources([
        './custom-element-one',
        './custom-element-two'
    ]);
}

Where it gets index/ from I guess I will never know, but this works at least.

I did need the babel plug-in Marton mentioned too, but that alone did not solve the mystery of the made up path.

Edit: To elaborate a bit further, if I name my main entry point something other than index.js the folder too needs that name. For example, if I were to rename index.js main.js I would need to put my globalResources inside a folder called main/.

查看更多
登录 后发表回答