Aurelia

Aurelia Beta Week - Day 2 - Plugins

Introduction

Aurelia

Aurelia


Aurelia Beta Week - Day 2 - Plugins

Posted by Aurelia on .
Featured

Aurelia Beta Week - Day 2 - Plugins

Posted by Aurelia on .

Yesterday, after months of work, we launched the Beta 1 release of Aurelia. From the beginning, one of the most important aspects of Aurelia's architecture has been its modularity and its pluggable design. In light of that, we wanted to dedicate one of this week's posts to plugins: What are they? What is available? and What are our plans?

What is a Plugin?

Aurelia integrates well with 3rd party libraries. Just jspm install the library you want to use, import it in your JavaScript module and then start coding with it. Some libraries may be built specifically for Aurelia. As a developer, you use those in the same way: install, import and code. However, the author of an Aurelia-specific library may choose to take advantage of our plugin model. By implementing a library as a plugin, the plugin author has the opportunity to run code as part of Aurelia's startup sequence, before anything is rendered. A plugin is provided with the same FrameworkConfiguration instance that is available to the app developer during the bootstrapping phase. As a result, a plugin can configure Aurelia in any way it wants. Typical tasks for a plugin might be to register services in the dependency injection container or customize some part of Aurelia's configuration. They might even do feature detection and install polyfills where appropriate.

What is available?

We have a set of plugins that we release regularly with Aurelia and wanted to share a little more information about them. We'll discuss the purpose each plugin serves as well the direction we foresee each going in.

Standard Plugins

You've probably already been using the standard plugins in your app. They are automatically installed anytime you install aurelia-bootstrapper. If you've launched an app with an empty aurelia-app attribute or used a custom main.js file to bootstrap your application, calling into aurelia.use.standardConfiguration() as part of that process, then you've been using the standard plugins.

The standard plugins provide functionality that "feels" like it should be in the core. However, it's important to note that, because of Aurelia's pluggable design, none of it is required. You can swap them with your own implementations. Most of them can be left out entirely, if not needed. However, we provide the above convenience methods for plugging the full set of standard plugins in, because 99% of the time that's what you want.

history

The history implementation for aurelia is split into two libraries:

  • aurelia-history - Provides a base history abstraction only, the History class, allowing other libraries to integrate with history while not being tied to a particular implementation or platform.
  • aurelia-history-browser - Provides the standard implementation of the abstract History class defined in aurelia-history.

At startup, when you call aurelia.use.history() or aurelia.use.standardConfiguration(), the history plugin will be installed. This causes the default history implementation defined within aurelia-history-browser to plug itself into Aurelia by registering in Aurelia's dependency injection container so that it is resolved when any component asks for the abstract History class defined in aurelia-history.

This plugin is currently at Beta 1 status and was included in yesterday's release. It's an entirely optional plugin. If you are using the router, you will need an implementation of the History class. However, it doesn't have to be our default implemenation, if that's not desired.

router

The router is used to achieve client-side routing and UI composition. It's a completely optional plugin, but most developers expect this capability in a modern framework, so it's easy to plug in. Either call aurelia.use.router() or aurelia.use.standardConfiguration() to turn it on.

The router depends on two other libraries. The first is aurelia-history, discussed above. Note again, it doesn't depend on the implementation of History, only the interface. So, you can use the router plugin with a different history implementation.

The router needs to trigger UI composition within your page, but it's also designed to be decoupled from the templating engine. So, rather than manipulate views directly, the router provides two abstractions itself. The first is the RouteLoader which the router uses when it needs to load a component associated with a route. The second is the concept of a "view port" which is what the router can interact with to display the previously loaded component. While the router itself is implemented in the aurelia-router library, the implementations of these two abstractions are implemented in the aurelia-templating-router library, since they provide the bridge from the templating engine (component loading and rendering) to the router (history-based navigation).

This decoupling provides you with flexibility, should you need to change how route loading or UI composition works. It also enables the router to be used with 3rd party templating engines, if desired.

This plugin is currently at Beta 1 status and was included in yesterday's release. It's extremely feature rich, but we are planning a number of additional features for Beta 2. Don't worry, there are no breaking changes coming, only additions to enable common, real-world scenarios.

default binding language

You may not realize it, but Aurelia's binding syntax (.bind, .for, ${...}, etc.) is actually not hard-coded. The templating engine defines an abstraction for BindingLanguage that is actually implemented in the templating-binding library. This library forms the syntactical bridge between the templating engine and the binding engine. In Aurelia, each view can have its own binding language, but the BindingLanguage that is registered with the dependency injection container is the default implementation that will be used when a view-specific implementation is not declared.

Note: You really shouldn't use different binding languages across Views. This hook is provided as a general extensibility point which could be useful when migrating from other libraries or when needing a custom DSL for content management or other end-user content-creation scenarios. For examples of this extensibility point in action, see this Channel 9 video.

When you call aurelia.use.defaultBindingLanguage() or aurelia.use.standardConfiguration(), the default binding syntax implemented in templating-binding is installed. This plugin is currently at Beta 1 status and was included in yesterday's release.

default resources

Not only is the binding language pluggable, but so are all our default templating resources. What are those? Those are things like repeat, compose, if, etc. The templating engine doesn't define these, rather, it defines a set of low-level templating primitives that enable any developer to build these constructs. Some of these constructs are so common and expected that we provide them out of the box. Those implementations are in the templating-resources library.

Any time you call aurelia.use.defaultResources() or aurelia.use.standardConfiguration(), the default templating resources implemented in templating-resources are installed. This plugin is currently at Beta 1 status and was included in yesterday's release. We are continuing to do performance work inside this plugin, but again, there's no need to worry about breaking changes.

event aggregator

In component-oriented architectures, there's often a need for cross-component communication. Usually, this is handled by an external message broker or "event aggregator" that provides the ability to publish and subscribe to messages or channels. The need for this comes up so often that we have the event-aggreagtor plugin to handle the scenario.

When you call aurelia.use.eventAggregator() or aurelia.use.standardConfiguration() the event-aggregator library will be installed and the singleton Aurelia object instance will be transformed into an event aggregator. As a result, you can have either EventAggregator or Aurelia injected into any component and use that for app-wide pub/sub.

This plugin is currently at Beta 1 status and was included in yesterday's release.

Official Plugins

In addition to the standard set of plugins described above, we also maintain a set of core plugins which are not distributed as part of the standard configuration, but are used very frequently. Each of the plugins below needs to be installed through jspm as well as plugged in to Aurelia via the aurelia.use.plugin(...) API.

animator-css

The templating engine provides a core abstraction known as Animator. The Animator is called whenever certain view operations are performed, such as adding or removing a view. The default implemention is a "no op", meaning that no animations happen. However, you can plug in an implementation that performs animation using whatever library you like. One of the official implementations is the animator-css plugin. This plugin provides animations based on CSS.

To install: jspm install aurelia-animator-css
To activate: in main.js configure, call aurelia.use.plugin('aurelia-animator-css');

This plugin is currently at Beta 1 status and was included in yesterday's release.

animator-velocity

Similar to animator-css the animator-velocity plugin provides an implementation of the Animator functionality. Instead of using pure CSS though, this implementation uses the velocity animation library.

To install: jspm install aurelia-animator-velocity
To activate: in main.js configure, call aurelia.use.plugin('aurelia-animator-velocity');

This plugin is currently at Beta 1 status and was included in yesterday's release.

fetch

When writing a JavaScript front-end, you'll typically need to load data from somewhere using HTTP. You can use any AJAX library you wish with Aurelia, but we're providing one based on the new WHATWG Fetch specification.

To install: jspm install aurelia-fetch-client

This library isn't currently required to be installed as a plugin, however, you will likely need an additional polyfill, since Fetch isn't available in all browsers.

To install the polyfill: jspm install fetch

After the polyfill is installed, in your main.js you'll want to simply import 'fetch'; at the top of the file to ensure that it is loaded.

This plugin is currently at Beta 1 status and was included in yesterday's release.

dialog

Modal dialogs are a common UI requirement. So, we are providing an official plugin for that. Typically the modals that need to be shown in an application are presented when some event takes place such as clicking on an edit button. The dialog plugin facilitates this behavior by creating a modal from the view-model/view that you provide. This allows displaying your own custom modals rather than being stuck with markup that you have no control over.

To install: jspm install aurelia-dialog
To activate: in main.js configure, call aurelia.use.plugin('aurelia-dialog');

This plugin was included in yesterday's release, however it does not have a Beta version number. The plugin is still undergoing some big changes in order take advantage of the latest features in the Aurelia core and unify it with other UI efforts that we are working on. As we make releases, we'll continue to provide notes on any breaking changes in this library. This plugin will be stable correspondent with the full framework Beta 2 release. We'll move it to Beta 1 before that, in the not-too-distant future.

i18n

The aurelia-i18n plugin provides internationalization and localization to your app through the i18next library. The library works through the use of translation files that match codes passed in to a custom attribute to a matching translation in the selected language.

To install: jspm install aurelia-i18n
To activate: in main.js configure, call aurelia.use.plugin('aurelia-i18n');

This plugin was included in yesterday's release, however it does not have a Beta version number. The plugin is still undergoing some changes in order take advantage of the latest features in the Aurelia core. Namely, we believe we can improve developer experience and simplify things by leveraging Aurelia's new binding behaviors. This plugin will be stable correspondent with the full framework Beta 2 release. In the future, we'll also have some tools around localization to accompany this plugin.

ui-virtualization

The virtualization library focuses on allowing the UI to perform various aspects such as scrolling through extremely long lists of items in the DOM or virtualizing those lists. Many mobile devices implement the same concept but with Aurelia we do so in a manner which is performant through the ui-virtualization library.

To install: jspm install aurelia-ui-virtualization
To activate: in main.js configure, call aurelia.use.plugin('aurelia-ui-virtualization');

This plugin was included in yesterday's release, however it does not have a Beta version number. The plugin is still undergoing some changes in order take advantage of the latest features in the Aurelia core. This plugin will be stable correspondent with the full framework Beta 2 release.

validation

The validation library allows observing changes to data to make sure the data matches preset validators. The validation uses a fluent API for chaining on validators. The long-term goal for the validation library is to break itself out into at least two libraries - one for validating data that is less dependent on Aurelia itself and another which handles the templating pieces such as displaying error messages to the user.

To install: jspm install aurelia-validation
To activate: in main.js configure, call aurelia.use.plugin('aurelia-validation');

This plugin was included in yesterday's release, however it does not have a Beta version number. The validation library is currently undergoing a major refactor. We plan to refactor the manipulation of the DOM away from the library and into aurelia-templating-validation implementations which allow the consumer to choose how to manipulate the DOM in response to validation errors. This will provide greater flexibility in integrating with various CSS libraries as well as allow us to share more code with other validation frameworks, such as BreezeJS.

3rd Party Plugins

All the above plugins are officially maintained by the Aurelia Core Team. However, there are other plugins created by our team members on the side...and lots more created by different members of the community. For the moment, you can find a list of these plugins in the registry repository. If you have created a plugin for Aurelia that you want to publish, simply submit a PR to the plugin-registry.json file in that repo.

Here's a few examples of what you'll find already:

  • aurelia-computed
  • aurelia-async
  • aurelia-breeze
  • aurelia-auth
  • aurelia-firebase
  • aurelia-leaflet
  • aurelia-materialize-plugin
  • more...

The official plugins we've previously discussed are released along with the Aurelia core. However, 3rd party plugins may take some time to get updated when there are major changes. If you depend on 3rd party plugins, you usually will want to wait a few days before updating your app. It's also a great idea to contact the author of the plugin and offer them assistance if there is any work they need to do to get their plugin updated and released. This helps to foster a great community ownership over the Aurelia ecosystem and gives you a way to contribute on a deeper level.

Where we are going...

Plugins are an important part of the Aurelia ecosystem. In the future, you'll see additional, officially supported plugins as well as new ones from the community. We hope you'll consider whether you've got some cool tech that might make a nice Aurelia plugin. Since the list of plugins is growing steadily, we want to provide a nice way for you to search, find, install and configure useful plugins into your project. Be on the lookout for our online plugin explorer and deep integration with jspm in the future.

View Comments...