story about module management with angular.js
TRANSCRIPT
A Story about AngularJS modularization development
Munich Meetup #4
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-lodashhttps://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 registration2. 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 Productionbuild, 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 junksHow 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"
})
AngularAMDhttps://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.0import {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