The purpose of this post is to demonstrate how to use RequireJS AMD in combination with regular Angular dependency injection.

Angular supports DI out of the box, but the implementation differs from RequireJS AMD in that all resources have to be loaded upfront before they can be injected. Loading resources like controllers, services etc is typically done via regular script tags in index.html, but in this post I want to show an alternative to script tags by using RequireJS. One obvious downside to using script tags is the potential for a large and unwieldily index.html as the application grows. It may also lead to unnecessary loading of files that the user won't need if they don't use certain parts of the application.

The philosophy behind RequireJS AMD is to support lazy loading of files as the files are needed. Meaning, JavaScript files will not be loaded until a user visits a part of your site that requires those files. Angular's own dependency injection is in some ways in conflict with lazy loading, so unfortunately we won't be able to truly lazy load files in Angular on demand. However, we will be able to remove the script tags and trigger loading via RequireJS.

The following sample application is very simple, but the main point is to highlight how to set up an application with multiple modules and resources with nested dependencies.

The image below shows the project file structure that makes up the Angular application.

Below you can find the complete setup and dependency registration needed to wire up the application using RequireJS.

main.js (needed to configure RequireJS)

require.config({ baseUrl: '', paths: { 'angular': ['bower_components/angular/angular'] }, shim: { angular: { exports : 'angular' } } }); require(['application'], function (app) { app.bootstrap(); });

application.js (the main entry point for the application)

define(['angular','services/module','controllers/module'], function (angular) { var app = angular.module('angular-amd', ['angular-amd-services','angular-amd-controllers']); app.bootstrap = function () { angular.bootstrap(document, ['angular-amd']); }; return app; });
When using RequireJS we have to manually bootstrap the application, so instead of using ng-app we call angular.bootstrap()


define([], function() { var greetingController = function(greetingService){ this.greeting = greetingService.createGreeting(); }; return ['greetingService',greetingController]; });


define(['angular','controllers/greeting-controller'], function (angular,greetingController) { var module = angular.module('angular-amd-controllers', ['angular-amd-services']); module.controller('greetingController', greetingController); return module; });


define([], function() { var greetingService = function(personService){ var createGreeting = function(){ return 'Greetings, ' + personService.getPerson() + '!'; }; return {createGreeting:createGreeting}; }; return ['personService',greetingService]; });


define([], function() { var personService = function(){ var getPerson = function(){ return 'Jim Smith'; }; return {getPerson:getPerson}; }; return personService; });


define(['angular','services/person-service','services/greeting-service'], function(angular, personSvc, greetingSvc) { var module = angular.module('angular-amd-services', []); module.factory('greetingService', greetingSvc); module.factory('personService', personSvc); return module; });

At this point we have successfully wired up an Angular application with multiple modules and nested dependencies.

It turns out you can improve on the lazy loading aspect by adding a library called ocLaxyLoad into the mix. Check out my other article for more info.