From JavaScript mess to Cleaner Code - Step 4 - Aurelia

January 6, 2017    JavaScript Development Aurelia jQuery Clean Code

From JavaScript mess to Cleaner Code - Step 4 - Aurelia

We’ve looked at a simple JavaScript app from many perspectives. We started at plain jQuery, then looked at jQuery using OOP principles to clean up some code, Step 3 introduced KnockoutJs, TypeScript and RequireJs to de-couple using data-binding, provide typing, and easier modularity.

Now, It’s time to look at a new web frameworks and see how they help us write less code. I’ve been following AureliaJs for awhile and have accumlated many links over the past year. There are a lot of things I like about Aurelia, so I decided to start with Aurelia for Step 4. I’ll also be adding an Angular2 article and ReactJs. I believe those are also very viable frameworks (as well as others, but there is only so much time available to look into everything). At the time I’m writting this, I would choose Aurelia over React and React over Angular2. There are many factors which I hope to write about soon. This may change over time as I get opportunities to use the right tool for the job. I appreciate Rob Eisenberg’s vision to keep close to the W3 specs, convention over configuration and how Aurelia stays out of the way. React is a completely new paradigm for me and will require a lot of learning, but I’m impressed by it. Angular2 looks good too, but after a few months of playing with it and learning I’m a bit overwhelmed with all the configuration and testing capabilities (my thoughts on Angular2 testing and here are my Angular links).

To get started with Aurelia, start with the video tutorial on their website and if you have Pluralsight, I recommend the longer more indepth tutorial.

My Aurelia version of this project can be found in my Github project, but you can clone full repository that has several different project in it. I’m also realizing this approach of creating the same project in several ways is a good way to compare frameworks (though it needs some more complexity to make it a better comparison).

I started from JavaScriptServices with Asp.net Core using the dotnet new aurelia command. The Aurelia CLI is the way to go if you aren’t using .Net Core or want a CLI.

Main.ts

The main.ts is where Aurelia gets configured and started. It has a nice plugin system using middle ware. There is a lot more here that can be investigated.

 import 'bootstrap';
 import {Aurelia} from 'aurelia-framework';
 export function configure(aurelia: Aurelia) {
    aurelia.use
    .standardConfiguration()
    .developmentLogging();

    // Uncomment the line below to enable animation.
    aurelia.use.plugin('aurelia-animator-css');

    // Anyone wanting to use HTMLImports to load views, will need to install the following plugin.
    // aurelia.use.plugin('aurelia-html-import-template-loader');

    // The root is set to App by configuration and is the starting place of the application.
    aurelia.start().then(() => aurelia.setRoot());
}

App.ts, Router and App.html

Now that Aurelia is configured, we can configure for our specific application and setup the router. My app.ts is where I’m doing this. The code is very straight forward.

import { Router, RouterConfiguration } from 'aurelia-router';

 export class App {
  public router: Router;

  public configureRouter(config: RouterConfiguration, router: Router) {
    config.title = 'Aurelia Energy';
    config.map([
      // http://stackoverflow.com/questions/40348535/organize-by-folder-in-aurelia
      { route: ['', 'energy'], name: 'energy', moduleId: 'energy/energy', nav: true, title: 'Energy' },
      { route: 'energy-details', name: 'energy-details',
        moduleId: 'energy/energyDetailsView', nav: false, title: 'Energy Details'}
    ]);

    this.router = router;
  }
 }

App.html is our first component and the shell for the application

<template>
  <!-- download the nav-bar component's html -->
  <require from="nav-bar.html"></require>
  <require from="bootstrap/css/bootstrap.css"></require>

  <nav-bar router.bind="router"></nav-bar>

  <div class="page-host">
    <!-- all pages routed to will be put in Aurelia's router-view -->
    <router-view></router-view>
  </div>

Binding example

The default component/view is my energy component. I should split this out into a few more smaller pieces, for example the select year options would make a good component and the data table would as well. The select year options is a good example of some of Aurelia’s binding syntax. energy.ts has a yearOptions array (public yearOptions: string[] = [];) that gets filled up. Aurelia knows that energy.ts is the data context of energy.html from the convention.

Testing

The Skeleton Navigation project came with Gulp and Karma setup and a few test examples in Jasmine. I haven’t spent as much time as I should, but there are a few of my tests in test/unit/energy.spec.ts. To run the tests, just use gulp test in your command line. It runs the test in Karma which enables running the tests in multiple browsers in parallel and with a little work you can add this to your build, you may need some C# code or with TFS build you should be able to run it in node and capture the output (I just haven’t tried that yet).

Here’s part of the spec file:

import { Energy } from '../../src/energy/energy';
import EnergyDataApi from '../../src/energy/energyDataApi';
import RouterFake from './routerFake';
import HttpFake from './httpFake';
import { HttpClient } from 'aurelia-fetch-client';

describe('Given the energy module', () => {
    let energy: Energy;
    let energyDataApiFake: EnergyDataApi;
    let routerFake = RouterFake.createRouterFake();
    let httpFake = HttpFake.createHttpFake();
    beforeEach(() => {
        energyDataApiFake = new EnergyDataApi(httpFake as HttpClient);
        energy = new Energy(energyDataApiFake, routerFake as any);
    });
    it('Should should hide energy data if no data loaded', () => {
        expect(energy.showEnergyDataTable).toBeFalsy();
    });
    ....

It was nice to have all the Gulp tasks already. They also provided all the Gulp code to bundle for prod. However, I recommend the CLI or the JavaScriptServices template over this one.

The Good

  • The framework takes care of routing, binding, module loading, etc. It makes it easy to make a Single Page App (SPA).
    • We didn’t have to decide on RequireJs vs something else, or KnockoutJs or JQuery. We just follow the Aurelia teams direction.
  • The Aurelia CLI (Command Line Interface) is very helpful.
  • I didn’t have to bring in Gulp or Grunt or other to do the building and minification. Webpack is all we need.
  • “For Aurelia, standards compliance is very, very important”
  • Convention over configuration
    • example: energy.ts ties to energy.html automatically
  • Components everywhere!
  • TypeScript! I don’t think I’d do much JavaScript work without TypeScript. It has been that valuable to our project.
  • It feels similar to using Knockout, but without all the confusing parenthesis.
  • You get to depend on the team or community behind the framework.
  • You get to learn a new approach to web development!
  • Hot Module Reloading is now supported (browser refresh isn’t needed and state is saved)

The Bad

  • There are many frameworks, how do you choose?
  • Using any framework requires learning. Are you up for it? Are your teammates?
  • More bytes for the client to download than you could possibly do on your own.
    • Of course, that argument goes away quickly if you are using jQuery or other libraries.
  • You have to depend on the team or community behind the framework

I encourage you to explore Aurelia and my code more. I’m excited about Aurelia and hope to use it in a real project someday. I also hope that it isn’t overshadowed by Angular2 and React :-), but that’s a discussion for another day.

Checkout out Step 4-2 on Angular



comments powered by Disqus