M41 Highway

Data science and software engineering blog


Leave a comment

Apply Dependency Control on AngularJS

ng require

 

 

Appreciated to the JS community for minify and uglify tools so we save much bandwidth for the web apps and the mobile apps. To uglify and concatenate java scripts files make the download more efficient. Meanwhile modularization and dependency control is important in application development with growing complexity. I was hesitate to apply dependency control on the AngularJS application with the two ideas come from opposite ends, until i see the talk by Thomas Burlesonabout Angular and Require JS. As a frontend developer, I like DI that really make code cleaner. Why not take one more step forward to incorporate the dependency control just like the way we code in backend application. Some people argue that it does not worth because a single concatenated file in production don’t bother you to manage the dependencies at all. But I see its value when we need to incorporate pretty much javascript plugins with AngurlarJS webapp in development time.

If you are reading up to this point, I assume you have the knowledge about AngularJS and/or RequireJS, and intend to integrate both, just like me, but there are not much practical information on the web. RequireJS is easy to use. Rather apply it directly to our existing project with fair complexity, I would take an approach to integrate it with a seed project from scrap, and I also take this chance to share how to get it done.

First of all, I use the popular Phonecat tutorial as an example to work with RequireJS. If you haven’t tried it before, please take a look at AngularJS.org. And you can get all the source code on my github for reference.

Modular design is good, but lack of dependency control is bad. Particularly when the Angular webapp become large and complex. It causes program break if the order of modules are not loaded in the order as expected. The followed diagram shows the dependency of the phonecat app. The phonecat module runs successfully only if all other modules are downloaded.

phonecat-dependency

 

So you would prefer screen B to A as it load module more as the way you expect.

phonecat-async-scripts-loading

Screen A: Javascript files request at the same time but no guarantee when to complete.

 

phonecat-async-scripts-loading-with-requirejs

Screen B: Javascript files are downloaded as the sequence as the dependency order

 

Okay, the idea is simple and we make the magic now. Let’s see the project structure shown in the followed image. The js folder is a typical template of AngularJS project with modules named animations, app, controllers, directives, filters, and services. Second, the main.js is the config file to define the dependency between the modules. In the lib folder, you need the RequireJS libaray. Third, I need to modify the index.html to add a bootstrap point to the RequireJS config.

directory-structure

In the main.js, you need to 1) define RequireJS module with an id and its file path in the “paths” block. It includes external Javascript library such as jQuery and AngularJS, as well as the customized module for example the Angular modules in this case. 2) define the inter-dependency between the RequrieJS modules in the “shim” block. Third we don’t need include script any more, instead we need define a callback method to trigger the bootstrap when the app module is loaded.

main.js

Forth, the ng-app attribute is removed so that bootstrap initialize the webapp. Fifth, you don’t need to script include for all the javascript files anymore, instead you only need one script include to define the path of the config file and the RequireJS library.

 

index.html

The setup is already done. Now we can inject the dependency in your program (in a similar way you import the classes in Java) by wrapping up the code with a define function and a callback. The followed five screen shots show how easy it is, but be careful not to mix up the RequireJS module id and the Angular module id.

app.js

animate.js

controller.js

filters

services.js

Here it is done. I hope you enjoy and it would be helpful.