KEMBAR78
A Story about AngularJS modularization development | PDF
A Story about AngularJS
modularization development
Munich Meetup #4
Johannes Weber
me@jowe.cc
@jowe
Developer at
David Amend
David.Amend@it-amend.de
Frontend Architect at
How to handle cross file
dependency management in my angular app ?
You could use Script Tags!
- You care manually about the ordering
- No magic - you add each file dependency by your own
- download happens synchronous
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript" src="/js/AppConfig.js"></script>
<script type="text/javascript" src="/js/auth/AuthService.js"></script>
<script type="text/javascript" src="/js/auth/RegisterResource.js"></script>
<script type="text/javascript" src="/js/auth/RegisterService.js"></script>
What’s about loading more these 5 scripts?
...how could I handle this?
You could use AMD!
- scoped thirdparty
- correct order of “mc” + “angular.module”
- framework independant
- async file loading of all dependencies
define([“lodash”, “angular”, “mycomponents”], function(_, angular, mc) {
mc.setModel(friends: [{name : “Peter”, age : 35}]);
return angular.module('myApp', ['mycomponents'])
.controller('MyCtrl1', [‘myService’, function (myService) {
//...
}])
});
AMD: what’s that?
“mycomponents” is duplicated! Why?
define([“lodash”, “angular”, “mycomponents”], function(_, angular, mc) {
mc.setModel(friends: [{name : “Peter”, age : 35}]);
return angular.module('myApp', ['mycomponents'])
.controller('MyCtrl1', [‘myService’, function (myService) {
//...
}])
});
AMD, cool! But what’s this?
“myservice” is duplicated! Why?
● AMD + Angular Dependency
define([“angular”, “myservice”], function(angular, mc) {
mc.setModel(friends: [{name : “Peter”, age : 35}]);
return angular.module('myApp', ['myservice'])
.controller('MyCtrl1', [‘myService’, function (myService) {
//...
}])
});
DRY!
angulars DI?
define([“angular”, “mycomponents”], function(angular, mc) {
mc.setModel(friends: [{name : “Peter”, age : 35}]);
return angular.module('myApp', ['myservice'])
.controller('MyCtrl1', [‘myService’, function (myService) {
//...
}])
});
AMD
angular
1.
2. 3.
angulars DI?
define([“angular”, “mycomponents”], function(angular, mc) {
return angular.module('myApp', ['myservice'])
.controller('MyCtrl1', [‘myService’, function (myService) {
mc.setModel(friends: [{name : “Peter”, age : 35}]);
}])
});
AMD
angular
1.
2. 3.
$script([
'bower_components/angular/angular.js',
'bower_components/lodash/lodash.js',
'dist/app.js'
'dist/mycomponents.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
global libs for complete app
define([“mycomponents”], function(mc) {
angular.module('myApp', ['mycomponents'])
.controller('MyCtrl1', [‘myService’, function (myService) {
mc.setModel(friends: [{name : “Peter”, age : 35}]);
//...
}]) });
3.
angular
→ used in any file !
load order must be handled?
→ anything loaded before angular.bootstrap
→ no code outside of angular.module
$script([
'vendorLibs.min.js',
'myapp.min.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
How to deal with vendors?
angular + lodash
- polluting global namespace?
lodash → not used anywhere
define([“mycomponents”], function(mc) {
angular.module('myApp', ['mycomponents'])
.controller('MyCtrl1', [‘myService’, function (myService) {
var _ = myNamespace.vendorLibs.lodash;
//...
}]) });
How to deal with vendors?
polluting → namespacing
How to deal with vendors?
Use existing modules: angular-lodash
https://github.com/rockabox/ng-lodash
var app = angular.module('yourAwesomeApp', ['ngLodash']);
define([“mycomponents”], function(mc) {
angular.module('myApp', ['mycomponents'])
.controller('MyCtrl1', [‘myService’, ‘lodash’, function (myService, _) {
_.random(10);
//...
}]) });
revise angular.module order issue
angular.module('mycomponents',[])
angular.module(myapp, ['mycomponents']).service( … )
→ How to guarantee order ?
1. module registration
2. module getter
angular.module('mycomponents', [])
angular.module('mycomponents')
angular.module('mycomponents', [])
angular.module('myapp', ['mycomponents'])
angular.module(myapp).service( … )
→ Does this work ?
...
angular.module('mycomponents', [])
angular.module(myapp).controller(function(dataService){ … )
angular.module('myapp', ['mycomponents'])
angular.module(mycomponent).service(“dataService” )
angular.module('mycomponents', [])
angular.module('myapp', ['mycomponents'])
angular.module(myapp).controller( … )
angular.module(mycomponents).service( … )
angular.module(myapp).service( … )
applicationContext.js → module registration
[src/**/*.js, !applicationContext.js] → module getters
...
You can use a gulp task for that
gulp.concat([
"applicationContext.js",
"src/**/*.js"
]);
…but AMD
- handle correct loading order
- anonymouse function
- additional effort
- async: no support for all frameworks
→ solving dependency management ?
→ solving namespacing ?
→ solving async ?
Are you using A of AMD, only for DEV ?
Loading 100 single files in the browser ?
Do you distinguish between DEV and PROD?
Do you distinguish between
dev and prod with AMD ?
app.js
JS Dependency Levels
app.js
JS Dependency Levels
Development Production
build, minified, concatinated
vendorLibs.min.js
JS Dependency Levels
Production Production
Splitting your source into junks would be nicer!
app.js
JS Dependency Levels
appTemplates.min.js
myapp.min.js
$script([
'vendorLibs.min.js',
'vendorLibs2.min.js',
'myapp.min.js'
'mysubapp.min.js'
'mycommonComponents.min.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
Actually you want to dev/deliver junks
How to ?
angular.module('mycomponents', [])
angular.module('myapp', ['mycomponents'])
$script([
'myapp.min.js',
'mysubapp.min.js',
'mycommonComponents.min.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
applicationContext inside
angular.module(myapp).controller( … )
Async
Loader
angular-loader module
<script type=”text/javascript”>/*angular-module-loader code here*/<script>
$script([
'myapp.min.js',
'mysubapp.min.js',
'mycommonComponents.min.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
angular.module('mycomponents', [])
angular.module('myapp', ['mycomponents'])
angular.module(myapp).controller( … )
How about commonjs and others ?
How about CSS/HTML/Images
(webpack) ?
How to lazy load junks of code?
- just less/no SPA ?
$script([
'mysubapp.min.js',
'mycommonComponents.min.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
$script([
'myapp.min.js',
'mycommonComponents.min.js'
], function() {
angular.bootstrap(document, ['myApp']);
});
app/index.html
app/subapp/index.html
How to handle
dependencies from
app to app ?
somehow with ui router … AMD?
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/state1");
$stateProvider
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html"
})
AngularAMD
https://github.com/marcoslin/angularAMD
app.config(function ($routeProvider) {
$routeProvider.when(
"/home",
angularAMD.route({
templateUrl: 'views/home.html',
controller: 'HomeController',
controllerUrl: 'scripts/controller'
})
);
});
On Demand Loading
Angular.overmind
“Easy module isolation and lazy loading for Angular apps”
var overmind = angular.module('overmind');
overmind.apps = {
'/profile': {
ngModule: 'profile',
file: 'apps/profile/profile'
},
// ...
Angular.js 2.0
What are Modules in AngularJS 2.0
import {Inject} from 'di/annotations';
import {Grinder} from './grinder';
import {Pump} from './pump';
import {Heater} from './heater';
@Inject(Grinder, Pump, Heater)
export class CoffeeMaker {
constructor(grinder, pump, heater) {
}
brew() {
console.log('Brewing a coffee...');
}}
Angular 2.0
→ combining angulars DI with ES6 loaders
→ combining ES6 loader with angular
???
→ which is preferred long time strategy ?
The end
Outlook
Outlook: AngularJS 2.0
- removal of angular.module
- Loading through ES6 modules
- Dependency Injection, Inversion of Control,
annotations
What are Modules in AngularJS 2.0
More Info in @vojtajina annotated Slides
https://dl.dropboxusercontent.com/u/36607830/talks/ng-conf-di-v2-annotated.pdf
namespacing pattern
var mynamespace = mynamespace || {};
mynamespace.subspace = mynamespace.subspace || {};
mynamespace.subspace.app = mynamespace.subspace.app || {};
module pattern
mynamespace.myObject = (function(lodash){
var myprivateVar = 123;
var publicFunction = function(){return 'Peter';});
return {
publicFunction : publicFunction
}
})(vendorLibs.lodash);
Upcoming
What is a module ?
Integrate external dependencies
Package Manager
- maven
- rpm
- bower
- npm
...
My Project angular 1.3
angular-router
angular-ui
bootstrap
yamm3
http://www.globaldots.com/big-page-size-going-2014/
But: how to know about magic dependencies of
'vendorLibs.min.js'
→ bower.json
Using Bower for YOUR modules !
/someRepo
- mymodule/bower.json
- mysubmodule/bower.json
- vendor-libs/bower.json
- global-css/bower.json
/anotherRepo
- anothermodule/bower.json
Angular.module Graph
http://kyu-project.co/kyu.html
https://github.com/lucalanca/grunt-angular-architecture-
Inner Modules = namespacingTypeScript
import SayingsType = some.prefix.module.Sayings;
...
var myValue : SayingsType = {a: “red”, b: 2, c: true}
TypeScript to support traceability of usages
module myapp.body {
import MyserviceType = myapp.header.myService; → compiled + removed at build time
angular.module('myApp')
.controller('MyCtrl1', [‘myService’, function (myService : MyServiceType) {
var result = myService.fetchData('123');
//...
}]) }) };
declare module myapp.header {
interface responseData {
name : string,
age : number
}
interface myService {
fetchData(id : string) : responseData;
}
}
Myservice.d.ts
Dependencies @build+compile time
myApp/bower.json
devDependencies:
commonComponents : 0.0.2
TypeScript Compiler
- /src/**.*/*.ts
- bower_components/commonComponents/src/ **/*.d.ts
→ myApp.js
Read dependency
information by build tool
var bowerProps = fs.readFileSync(filePath, 'utf8').JSON.parse(bowerFile);
var deps = bowerProps.devDependencies.startsWith(“dab-*”);
TypeScript
import angular = require(“angular”)
JavaScript
CommonJS
import angular = require(“angular”)
AMD
define([“angular”], function(angular){ …}
ECMAScript6 Harmony
import * as angular from “angular”
TypeScript Outer Modules

A Story about AngularJS modularization development