Saturday, August 4, 2012

Modularizing an Angular app with AMD

How to create an Angular app that plays nice with AMD using Jam.


Setup

Installing Jam

The app's dependencies will be managed using AMD and RequireJS. 3rd party modules like Angular will be installed using Jam. Which will need to to be installed first. Jam itself is a npm artifact so if you don't have Node.js or npm installed you will need to do that before starting.

Installing AngularJS

With Jam installed you can now install 3rd party libraries like Angular in your project.

Note right now the angular artifact jam installs is not configured as a AMD module. You will need to use the global Angular object reference since AMD will not be able to provide the requested module.

Coding

We will start with the TodoMVC project for angular and adapt it into AMD modules.

Wrapping Angular App in AMD modules

Wrapping an Angular app in AMD modules is pretty straight forward you just need to export the Angular code so that it can be loaded. The biggest change will be with app.js file since you will not longer be exposing your app as a global var and will have to manually bootstrap Angular telling it to load your app.

app.js

The main thing here is to note that we are returning an object that can be loaded by other AMD modules so they can get a reference to the Angular module and it's factories.

todoBlur

Services and other Angular managed objects are pretty straight forward. You will need to load the app AMD module so you can call the factory methods on the Angular managed module.

I wish Angular had chosen something other than the term "module". Component or object would have made it easier to differentiate between AMD modules which are essentially a way of defining and loading source or code dependencies and Angular modules which are managed objects which can be injected.

Create main.js

This will be the main entry point to the application. It should load all the AMD modules containing Angular objects so they will be available when Angular bootstraps your app.

Updating index.html

Now that the application is wrapped with AMD modules you can replace all of the <script> tags with a single one that loads RequireJS. Setting data-main="main" tells RequireJS to load main.js as the root module.

Organizing

With the small todo example there is almost a 1:1 ratio between AMD modules and Angular modules. On a larger project you may want to create aggregator AMD modules which combine multiple AMD modules and export them or put multiple Angular modules in a single AMD module.

Reference

The full code is available here on Github.

Jam
A package manager for JavaScript for the frontend.
RequireJS
A JavaScript file and module loader for the browser.
AMD
The Asynchronous Module Definition (AMD) API specifies a mechanism for defining modules such that the module and its dependencies can be asynchronously loaded.
AngularJS
MVW framework for web apps.
npm
A package manager for JavaScript.
NodeJS
Non-blocking event driven javascript for the server.
TodoMVC
Example todo apps for lots of different frameworks.

5 comments:

  1. https://gist.github.com/3213752#file_todo_blur.js

    https://github.com/btilford/jam-plus-angular/blob/master/directives/todoBlur.js

    ReplyDelete
  2. Hi Ben,

    Great tutorial!

    Being a relative newbie to both AngularJS and jam/requirejs I wonder can you shed light on how, in this setup, I might cater for a dependency on the angular ngResource module, a separate file in the latest release of Angular (http://code.angularjs.org/1.0.1/angular-resource-1.0.1.min.js), and not in the jam package repository??

    Thanks,

    Al

    ReplyDelete
  3. Thanks for the guide!


    You might want to check the code for todoBlur - it doesn't match up with how it looks on GitHub, and looks very similar to the code in app.js.

    ReplyDelete
  4. Great tutorial! Exactly what I needed and couldn't find anywhere else! Thanks alot!

    ReplyDelete
  5. Great tutorial! I'm trying this out now. I would love for use jam + angularjs on my next project.


    Chris

    ReplyDelete