Enhance an existing page with Aurelia

Aurelia's Enhance feature

Many people use various techniques for improving page load times. One really nice way is to use isomorphic JavaScript, sometimes called universal or many other names. The technique is used to allow the pages to render with some content faster to both improve load times as well as give the user feedback faster that things are happening.

In Aurelia, we don't yet have the ability to say we officially support isomorphism, but that doesn't mean there isn't a way. In place of this I wanted to describe a technique for augmenting your existing page with Aurelia so that you can see the interaction between the server-rendererd page and Aurelia.

Introduction

Aurelia provides the ability to use the enhance feature so you can take a fully-functioning server-rendered application and start to augment it with some nice feature-rich custom elements.

Let's start first by looking at a simple static HTML page that we can use -

Setting up application

Grab the latest skeleton-navigation app

https://github.com/aurelia/skeleton-navigation/releases

Download the newest available release and open up a terminal and navigate to the folder it was downloaded in to.

Install dependencies
$ npm install
$ npm install -g gulp
$ npm install -g jspm
$ jspm install -y
$ gulp watch

Now we have a running application but let's make the index.html a static html page so we can augment it.

Grab the index.html from this gist and use it to replace our current index.html.

https://gist.github.com/PWKad/cf54d08d3e55a93a54ee#file-index-html

Last, let's remove the aurelia.setRoot from our main.js and replace it with the aurelia enhance.

Our main.js should now look like this-

import 'core-js';

export function configure(aurelia) {  
  aurelia.use
    .defaultBindingLanguage()
    .defaultResources()
    .developmentLogging()
    .globalResources("custom-table")
  aurelia.start().then(() => aurelia.enhance(document.querySelector('custom-table')));
}

We need to pass the element in to the enhance method, and also we need to globalResources on any custom elements we want to use. In this case we are grabbing a custom-table element and telling aurelia to enhance it. We will add that custom element in just a second. This is because we aren't using a full Aurelia app where we can simply import the elements;

We can call also aurelia.enhance on all of the other custom elements we want to enhance on the page.

Augment page

We have our static page now, let's augment it with a custom-table. Our custom table will just take the title for a table and make it clickable to toggle the table showing as well as a button at the bottom to do the same. In your application you could go much deeper but this is just to explain some concepts.

First, let's add an aurelia-app attribute on the body of our page with a value of main so the bootstrapper knows where the main entry point for Aurelia is -

<body aurelia-app="main">  
  <!-- ... -->
</body>  

This points to our main.js file we fixed up earlier and to enhance the custom-table. Now, let's wrap our table-header and table in a custom element that we can use to augment the content -

<custom-table>  
  <table-header><!-- ... --></table-header>
  <table><!-- ... --></table>
</custom-table>  

We could take a few different approaches to augmenting the content but for this walk-thru we are going to simply render the content inside our tag and augment it.

Creating our custom element

Let's go ahead and create a template to use - we'll put this in our src directory and name it custom-table.html so Aurelia conventionally knows how to load it.

<template>  
  <a click.trigger="toggleShow()">
    <content select="table-header"></content>
  </a>
  <div show.bind="isShowing">
    <content select="table"></content>
  </div>
  <div class="row">
    <div class="col-xs-6">
      <button click.trigger="toggleShow()">${isShowing ? 'Hide' : 'Show'}</button>
    </div>
  </div>
</template>  

Basically this will render the table-header inside of an anchor so clicking will toggle the table showing and adds a button as well that does the same.

Next let's create the corresponding view-model -

export class CustomTable {  
  isShowing = true;
  toggleShow() {
    this.isShowing = !this.isShowing;
  }
}

Now if we switch back over to Chrome and open localhost:9000 we can see that our page loads and our table is augmented once Aurelia has finished loading. We could add functionality or add custom elements all over different pages by following the same approach. In fact, if we work smartly enough we can use the same main.js for all of our pages and just make the custom elements we use all globalResources.

Conclusion

We can bundle and use other production workflows to improve the load times but for SEO purposes our page immediately renders and then the functionality is added.

I'd love to get your feedback in the comments section.