If I'm using Angular which is a framework to build Single Page Applications (SPA), maybe I should understand what an SPA is.

Of course there is the Wikipedia article, but I like this discussion of SPA's. It addresses my misconception that an SPA could house a simple CRUD workflow but it would take multiple "pages" to create a full fledged application. In actuallity a "single page" is the entry into the application. Then through the combination of HTML, HTTP, and JSON that single page is transformed is into the various views of the application. You don't link to other pages to get different functionality.

You also don't lose browser navigation which surprised me. I thought doing DOM manipulation on this level would break the web paradigm, but it doesn't so I'm going to need to learn how Angular does this.

On a funny note, the author likes the term Rich Web Application which makes me think he didn't live through the horror of Rich Internet Applications. Nobody in their right mind would want any connection with Flash, Silverlight, or any of the other abominations that polluted the web.

Where I spend a couple hours learning that I don't know what I'm doing.

After my dive into the configuration files I felt like I had a pretty strong base to start from. I know what packages I'm using and what they do. I started by tweaking one end to end test to expect 'Small Catechism Flash Cards' as the header, compiled (missed that the e2e test script didn't compile automatically), ran the e2e test, and saw a failure. I then changed the Angular component, compiled, and ran the test and voila it passed. BDD at its finest! (Obviously my overconfidence was setting me up for failure.)

I thought, "Why not try to display a card, and so I don't get too far ahead, just the title of the card and what would be the front text." So I wrote a test that looked for 'The Ten Commandments' in an h1 and 'The Introduction' in an h2. The URL to access would have the form /set/1/1 (set for the resource /). I think I made a mistake in assuming this is how the card should be accessed in the application. It might make sense for an API to retrieve the card, but maybe not the way to do it for the UI, not sure yet.

The URL format lead me to investigate how to respond to the /set// URL. This lead me to routers. I looked at the book I'm working through and started to work off that example, but found that some of the components I was trying to import weren't there. I then found that the way routers are being handled has changed since rc0 (What? I thought API's were stablized at beta guess that was a bad assumption knowing that the Gmail was in public beta for 5 years). I tried to use the new route style, but kept getting a 404 when I tried to use them. I looked for a fix for a bit, but ended up assuming this was some bug since the documentation isn't complete I'm not betting the implementation is complete either. What I ended up doing was using 'router-deprecated' and using the examples from the book. After a few more missteps, and learning I needed to define a base href in my index.html I got a page up responding to /set/1/1, but not doing at all what I expected.

I looked at the example some more and I don't think this is the way I'm supposed to be writing the angular app or using routers. I'm going to pull back a little bit and study the philosophy of what makes a good Angular app, the proper use of components, and how to use routers.

tslint.json setups the linter for TypeScript code.

Discussing this file would just be going over minutae. The parameters are pretty self explanatory. I've never used a linter and relied on manual adherence to any coding standard. I'm not sure I will use it, but it might be interesting to see how my style differs from the default style and if I like the defaults. I will be impressed if I find lint useful enough that I end up changing some of the defaults.

To configure Karma, the test runner, there are karma.conf.js and karma-test-shim.js.


First, the 'framework' is set to Jasmine. Then karma-jasmine, karma-chrome-launcher, and karma-htmlfile-reporter are set as required plugins and 'customLaunchers' is set to launch the Chrome browser.

Next there is a big block that tells which files are to be sent to the browser and which are to be served by the Karma webserver.

The next interesting configuration is for the reporters which is set to 'progress' and also 'html' which is configured in the next block and is set to output a tests.html file at the end of the test run.

Lastly, some miscellaneous items like the the port, colors (for reporters and logs), logLevel, autoWatch (for automatically running the tests if a file changes, the browser (Chrome), and singleRun which tells Karma to run the tests once and then exit (false).

typings.json tells the TypeScript compiler how to handle certain JavaScript libraries.

In typings.json definitions for how to handle Jasmine and es6-shim are configured.

Up next, systemjs.config.js which configures the SystemJS module loader.

The map block configures a module alias to a location or package. 'app' maps to the ./app directory. 'rxjs' maps to node_modules/rxjs, 'angular2-in-memory-web-api' maps to node_modules/angular2-in-memory-web-api, and '@angular' maps to node_modules/@angular.

The packages block allows configuration of a particular map. 'app' is configured with a main of main.js and defaultExtension is set to js. 'rxjs' and 'angular2-in-memory-web-api' are configured with defaultExtension set to js as well.

Finally, there's some actual JavaScript code to set defaultExtension to js for all the @angular packages and System.config() is called with the configuration block to make the changes to the system.

Time to look at tsconfig.js which is used to configure TypeScript.

The first block configures the compiler options. The target option is set to es5 so the ECMAScript target version is ECMAScript 5. The module option is set to commonjs so CommonJS is used for module loading. The moduleResolution is set to node so the compiler mimics Node.js's runtime module resolution. The sourceMap option is set to true so that .map files are generated (.map file are created so debuggers can map compiled code to the source). The emitDecoratorMetadata and experimentalDecorators are set to true to support class metadata using decorators. The removeComments option is true so that comments are available in the compiled .js file. The noImplicitAny and suppressImplicitAnyIndexErrors are set to true so the compiler is more strict and will fail if a type cannot be inferred.

The next block is the exclude section which tells the compiler what directories to ignore. The node_module, typings/main, and typings/main.d.ts are set to be ignored by the compiler.

Another useful excercise in learning what's going on with an Angular project. Steady progress for the win!

I purused the package.json file and tried to learn a little about the application's configuration and what modules are being imported.

After the name, description, and version number of the application came a big json block for scripts. These scripts are shortcuts to run various commands for compiling, starting the server, running tests, etc. Something I learned was the 'concurrently' command. This allows multiple commands to run concurrently. For example, the 'start' command includes concurrently \"tsc -w\" \"lite-server\" which starts the server and watches for files that change so they can be recompiled.

The next major block was for dependencies. It included the '@angular/' construct to include Angular 2 which is different then running 'npm install angular2 --save' which I've seen everywhere else. Installing angular2 only gets you to beta 17 whereas with @angular/ you can get rc 1. I don't know if you will always have to configure package.json or if there will be a way to 'npm install' the latest angular2 or @angular/. Additional dependencies include systemjs for module loading, es6-shim for JavaScript compatibility, reflect-metadata for adding metadata to a class, rxjs for handling of asynchronous and event-based programming, zone.js for creating context for asynchronous operations, angular2-in-memory-web-api for simulating data, and bootstrap for the front-end framework.

Finally are the devdependencies; the modules used for development. They include the previously mentioned concurrently, lite-server for a lightweight web server, typescript the TypeScript programming language the project uses, typings for managing TypeScript definition, canonical-path for easier multi-platform path management , http-server for a more robust web server, tslint for checking TypeScript syntax, lodash a JavaScript library for arrays, strings, etc., jasmine-core for BDD, karma for getting tests to run in the browser, karma-chrome-launcher for helping karma launch the Chrome browser, karma-cli to allow Karma to be used from the command line, karma-htmlfile-reporter adds a Karma plugin that exports test results as a styled HTML file, karma-jasmine an Karma plugin that enables it to run Jasmine tests , protractor for end-to-end testing, and rimraf for easily deleting directories.

I think going through that was worthwhile. Typically, I would have just copied the package.json from somewhere and just used it until I ran into a problem. Taking a more thorough approach is something I want to do right now and it gives me a sense that I'm making steady progress.

Reading the README.

I spent time today reading through the README file and setting up a GitHub project based on the Angular QuickStart. I didn't do any modifications yet, just checked-in the base project. I also ran through the unit and end-to-end (e2e) tests. I didn't know what Protractor was until I saw the config file and read that it was the e2e test framework. Guess I'll have to add that to the list of config files I need to dig through and understand.

My plan for the next couple days is to read through and understand the package.json, tsconfig.json, and systemjs.config.js. After those three, I'll decide which to tackle next, but I still plan to have a decent grasp of all the configurations before moving on to actually writing some tests.