Saturday, August 4, 2012

Modularizing an Angular app with AMD

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


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.


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.


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.


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.


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.


The full code is available here on Github.

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