AngularJS
with
RequireJS
Thomas Burleson
SiriusXM Satellite Radio
Preview
Take-away Summary
-
AngularJS injects instances
-
RequireJS injects Classes
RequireJS
Is it
needed
with AngularJS
?
Fast-dive into
RequireJS
concepts...
How
to use
RequireJS
with
AngularJS
?
Is RequireJS really needed ?
Option #1: Load all the code in one large Javascript file (or block)
var FlightDashboard = function( $scope, user, travelService ) { /* ... */ },
$QDecorator = function ($provide) { /* ... */ };
angular.module( "FlightServices", [ ] )
.config( $QDecorator )
.service( "user", function() { /* ... */ })
.service( "travelService", function( user, $q ) { /* ... */ })
.service( "weatherService", function( $q ) { /* ... */ })
angular.module( "FlightApp", [ "FlightServices" ] )
.controller( "flightDashboard", FlightDashboard );
... reasonable for simple apps.
See the code dependencies !
... for a simple app!
Option #2: Let's use Packages instead...
... but we still have to manually manage the loads ( aka imports )
What about large apps ?
Imagine the dependency complexities !
for real-world application code !
We need a
Package Dependency Manager
( aka Linker )
Fast-Dive into RequireJS !
4 Dependency Types
4 Great Features
3 Simple APIs
4 Types of Dependencies
Load
Dependency
Construction
Dependency
Runtime
Dependency
AngularJS Module Dependency
4 Great features using RequireJS
!
1) Package
Dependency
Manager
2) Injector ( note: this not AngularJS Injection )
3) Javascript File Loader
4) Concatenate / Uglify
RequireJS manages :
- Load dependency
- Runtime dependency
Angular JS manages :
- Construction dependency ( IoC )
- Angular Module dependency
3 Simple RequireJS APIs
1)
define
( )
- define dependencies & register factory function
2)
require
( )
-
callback function to be invoked; when
the tree of all define()s have completed
the tree of all define()s have completed
3)
requirejs
.
config
( )
- configure source paths & aliases
1.) define ( )
Creates Asynchronous Module Definitions
(
AMD
) so files
load in any order.
`
Ready
` handlers called when
dependencies resolve...
trigger
immediately if no dependencies.
`Ready` handlers
return values
which are stored by filename or ID...
Values
are injected into ready handlers of other AMD definitions.
-
Every file is wrapped in a define()
-
Every define() returns a value; cached in registry
1.)
define
( )
define(
[ ], // array of dependencies `paths` to other define() modules
function onReady( )
{ /** * Returns a value (Function, Constructor, String, Object, etc), */ } );
- The anonymous function is named onReady
-
onReady
is called immediately since no dependencies.
- onReady must return an Object ( Function, Class, or instance)
- The Object is stored in internal RequireJS registry
1.) define( ) with no dependencies :
define([ ], function ( ) { var supplant = function( template, values, pattern ) { pattern = pattern || /\{([^\{\}]*)\}/g; return template.replace(pattern, function(a, b) { var p = b.split('.'), r = values; try { for (var s in p) { r = r[p[s]]; } } catch(e){ r = a; } return (typeof r === 'string' || typeof r === 'number') ? r : a; }); }; return String.supplant = supplant;
});
- filename == ./mindspace/utils/supplant.js
-
Implicit dependency ID == mindspace/utils/supplant
1.)
define
( )
define(
[ 'mindspace/utils/supplant' ],
function onReady( supplant )
{
return XXX;
}
);
- Dependency on supplant.js file ( notice missing .js)
- Value returned from supplant.js define() is a Function
- Supplant() is only used within this AMD
- This AMD define( ) returns value XXX;
1.)
define
( )
with dependencies
:
define( [
'mindspace/utils/crypto/md5',
'utils/supplant'
],
function ( md5, supplant )
{
// Prepare the Gravatar Directive construction function
var Gravatar = function( ) { /*...*/ };
return Gravatar;
});
-
onReady arguments are injected Values; loaded by each dependent define()
-
Can use package
paths
as dependency
IDs
.
-
Can use use path `
alias
` notations also.
1.) define ( )
Builds a tree of dependencies
Builds a flat registry of values stored by module ID
Values are usually references to Class or Functions
But
NOTHING
happens until
require()
is used!
2.) require ( )
require( [ "main" ], function( app )
{
// Application has bootstrapped and started...
});
- Acts as the initialization or ROOT of the dependency tree.
- Starts the cascade of dependency checks and script loading
-
Starts the
cascade
of
define()
triggers
3.) requirejs.config ( )
require.config (
{
appDir : '',
baseUrl : './src', // relative to index.html
paths :
{
// Configure alias to full paths
'auth' : './quizzer/authentication',
'quiz' : './quizzer/quiz',
'utils' : './mindspace/utils'
}
});
- Configures locations to source & packages
- Configures aliases for define ( )
How to use RequireJS with AngularJS ?
So easy...
- Use define( ) around your modules...
-
Use define( ) around all your code...
-
Use requirejs.config( ) to set your paths
-
Use require( ) to launch your code to initialize AngularJS
AngularJS Controllers
define( [ 'utils/supplant' ], function ( supplant ) { var LoginController = function( session, authenticator, $scope, $log ) { $log.debug(
supplant( 'User {name}', session.user )
); }; return LoginController; });
-
RequireJS
is injecting Functions or Classes
-
AngularJS
is injecting
instances
of the classes
AngularJS Services
`quiz/delegates/QuizDelegate`
define([
'utils/Factory',
'quiz/builders/QuizBuilder',
'quiz/builders/ScoreBuilder'
],
function ( Factory, QuizBuilder, ScoreBuilder )
{
var quizBuilder = Factory.instanceOf( QuizBuilder ),
scoreBuilder = Factory.instanceOf( ScoreBuilder),
QuizDelegate = function ( $http, $q, $log ) { /* ... */ };
return [ "$http", "$q", "$log", QuizDelegate ];
}
);
RequireJS
is injecting
Classes
(definitions)
Instances
are constructed
external
to
AngularJS
to
be used within the
QuizDelegate
service...
AngularJS Modules
`quiz/QuizModule`
(function ( define, angular ) {
"use strict";
define([
'quiz/delegates/QuizDelegate',
'quiz/controllers/TestController',
'quiz/controllers/ScoreController'
],
function ( QuizDelegate, TestController, ScoreController )
{
var moduleName = "quizzer.Quiz";
angular.module( moduleName, [ ] )
.service( "quizDelegate", QuizDelegate )
.controller( "TestController", TestController )
.controller( "ScoreController", ScoreController );
return moduleName;
});
}( define, angular ));
AngularJS App
main.js
define([
'quiz/QuizModule',
'quiz/RouteManager',
'auth/AuthenticateModule'
],
function ( QuizModule, RouteManager, AuthenticateModule )
{
var appName = 'quizzer.OnlineTest',
depends = [ "ngRoute", AuthenticateModule, QuizModule ],
app = angular.module( appName, depends )
.config( RouteManager );
angular.bootstrap( document.getElementsByTagName("body")[0], [ appName ]);
return app;
}
);
GitHub Demo: Quizzler
Using Grunt
Build and Deploy
Supports RequireJS using grunt plugin
-
Deploy Uncompressed
-
Deploy Minified & Obfuscated
2 Secrets to Builds
(1) Configure Grunt RequireJS settings
requirejs: {
compile: {
options: {
baseUrl: "../client/src",
paths :
{
// Configure alias to full paths; relative to `baseURL`
'auth' : './quizzer/authentication',
'quiz' : './quizzer/quiz',
'utils' : './mindspace/utils'
},
out: '<%= buildDir %>/assets/js/quizzler.js',
name: 'main'
},
preserveLicenseComments : false,
optimize: "uglify"
}
}
2 Secrets to Builds
(2)
Configure Main launch point
head.js(
{ require : "./vendor/requirejs/require.js", size: "80196" },
{ angular : "./vendor/angular/angular.js", size: "551057" },
{ ngRoute : "./vendor/angular-route/angular-route.js", size: "30052" },
{ quizzler : "./assets/js/quizzler.js", size: "18762" }
)
.ready("ALL", function()
{
require( [ "main" ], function( app )
{
// Application has bootstrapped and started...
});
});
-
Load the
Uglified
app code in js/quizzler.js
- Use require( ) to trigger all define( ) & initialize AngularJS
AngularJS App
require( [ "main" ], function( ){ } );
define([
'quiz/QuizModule',
'quiz/RouteManager',
'auth/AuthenticateModule'
],
function ( QuizModule, RouteManager, AuthenticateModule )
{
var appName = 'quizzer.OnlineTest',
depends = [ "ngRoute", AuthenticateModule, QuizModule ],
app = angular.module( appName, depends )
.config( RouteManager );
angular.bootstrap( document.getElementsByTagName("body")[0], [ appName ]);
return app;
}
);
Demo
angularjs-Quizzler on GitHub
-
Development Build = 'grunt dev'
-
Production Build = 'grunt prod'
About ME
Thomas Burleson
-
email: ThomasBurleson @ Gmail.com
-
twitter: @ThomasBurleson
-
blog: www.solutionOptimist.com
- linkedIn: http://www.linkedin.com/in/ThomasBurleson
- code: https://github.com/ThomasBurleson
Need a senior, front-end architect ?
I am looking for the next great project...
Copy of Using RequireJS with AngularJS
By Denis Stoyanov
Copy of Using RequireJS with AngularJS
Why is RequireJS important to AngularJS development? Learn the how RequireJS augments your development o manage your code and packages and deliver it to AngularJS.
- 1,160