April 4, 2016

Let's Learn AngularJS

This is a look at how to assemble a basic Angular 1 application using webpack.

AngularJS is a javascript front-end framework that makes it possible to build rich interactive applications within modern web browsers.

Why Angular?

Why AngularJS when there are so many options to choose from?

  • Angular is popular

Popularity is not everything, but it does mean that Angular is not going away any time soon. Popularity is typically directly proportionate to the amount of support. This means better documentation, more tutorials, additional help, community support, and faster issue resolution and feature development.

  • Angular does MVC (model, view, controller) right

The single best thing about Angular is it lets you keep your logic and your presentation separate. This makes your logic much simpler. It also makes Angular applications easier to unit test.

  • Angular is complete

Angular has been around the block a few times. If you want to build it, there’s a way to do it in Angular.

  • Angular is looking to the future

The Angular team is actively developing the second generation of Angular. Included in this redesign will be ridiculous performance improvements and many simplifications. Writing in Angular is only going to get better. Later we’ll take a closer look at what is coming in Angular 2.0 and how you can be prepared.

Overview

I’ll demonstrate this application through a public repository on GitHub. We’ll build a basic Angular application. We will use npm to resolve our external dependencies (Angular). We will also use webpack to bundle all of our code files together into one easily deployable script. We’ll demonstrate briefly how webpack can minify and add source maps if desired.

The public repository is here: https://github.com/SonofNun15/explore-angular.

Creating an application

Getting an empty application up and running is simple.

Create a module for the application.

https://github.com/SonofNun15/explore-angular/commit/a790d0d24ccfbf585be0494569afcfa2cc6e2ac1

The first thing that you will notice is that we are using CommonJS modules.

var angular = require(‘angular’);
exports.moduleName = ‘exp-ang’;

Later on, we’ll use webpack to resolve these dependencies into a single script for our application. Webpack enables us to import / require our npm dependencies directly by name. We use this to eliminate a global dependency on Angular. Without the global dependency, all of our references are clear and explicit.

Next you may notice that we export the module name. Angular relies heavily on dependency injection. Your blocks of code will ask to have their dependencies injected in by name, using the name as a string. This typically creates a brittle dependency between types based only on the name of the dependency. To avoid this, we save all of our names and export them so that we can inject by name instead of using a magic string. You’ll see this in the next commit when we create a simple controller for our application:

https://github.com/SonofNun15/explore-angular/commit/8b7e3c1e52720c84ece12a1587eb5d27d3b883f3

You can see here how we use the exported name of the child module to specify the application dependency, avoiding repeating the name as a magic string (in app.js):

var helloWorldModule = require('./helloWorld/helloWorld.controller');
angular.module(exports.module, [
    helloWorldModule.moduleName,
]);

We could have opted to put the controller on the main application module. Instead, we created a new module for the controller, declaring this module as a child / dependency for the application module. Giving each cohesive angular component its own module keeps things more granular and organized. It also simplifies things when writing unit tests because we can isolate the tests against a single cohesive angular module. It also provides a single point of entry for our bundler (webpack). Our application module will require all of its child dependencies, so webpack can follow these links to convert our project tree into a single bundle script for deployment.

Enter Webpack

In our next commit, we configure webpack to bundle our application:

https://github.com/SonofNun15/explore-angular/commit/18eb8dd134ee5aea694ee66ad99b67bad83a7c84

For now, our config is very simple. We specify our main entry point and tell webpack where to put the resulting bundled script. To run webpack, you’ll need to have it installed first, which can be done via npm:

npm install –g webpack

On some platforms you’ll need to use sudo for a -g install. John Papa has some suggestions about this.

Now you can bundle your application using:

webpack

To minify the output, simply add the flag -p. Alternatively, you can build source maps by adding -d, which will let you debug against the original files instead of debugging inside of the bundle.

Only two simple steps remain:

https://github.com/SonofNun15/explore-angular/commit/b9586f2ee5bc7422d7ff6b76ecc7441125a0362f

Add an index with a reference to the bundled script. In our index, we instantiate our main angular module using ng-app="exp-ang". Then we create our controller on the header tag and alias it as "helloWorld".

<header ng-controller="HelloWorldController as helloWorld">

Unfortunately both the application module and the controller are referenced using their string names, creating a hard dependency on the names. We can limit our dependencies on names in angular, but we can’t eliminate them all together. Finally, we use Angular’s bind syntax {{}} to pull the message value off of the controller into the h1 tag.

Our final commit configures webpack to reference Angular from an external global, letting us remove Angular from our bundled script and instead pull Angular from a CDN.

https://github.com/SonofNun15/explore-angular/commit/e8775bedd255262df3dbab2c49866dbaffe1d3e7

Following along

GitHub repo: https://github.com/SonofNun15/explore-angular

To follow along with this post, clone the repository from the empty tag. All the repo has at this point is the readme and license plus the npm package definition and a gitignore file.

To see the finished product, clone the repository from the application tag.

Post progresses from tags:

empty -> application