AngularJS: Best practices

Best practices on writing Angular code for uniformity and performance

Posted by Aditya Pratap Singh on June 29, 2015

AngularJS has become one of the widely adopted javascript frameworks because of the vast benifits it provides in development lifecycle and code quality. With wide number of features it provides for a Single Page Application, their are some drawbacks to it in the way we use. I have discussed some of best practices to avoid the drawbacks of using angular:

  1. Have a modular directory structure: The directory structure is very important in organizing angular modules. This helps in not only organizing the code for everyone's understanding in team, but also good mainatinability and refactoring of code base. There are 2 mostly used app directory:
    • Component wise directories: This pattern emphasizes on using one directory per component type i.e. 1 directory each for directives, services, controllers, filters etc.
      app-compnents directory structure
    • Module wise directories: This pattern emphasizes on using one directory per module. Every module will have sub-directory for services, controllers and directives. The common components can be moved to a common module
      app-modular directory structure
  2. Single responsibility principle: One file should do only one task at a time This gives us the advantage of finding the files easily and maintaining the code better. Also bugs are inevitable evils as part of development process. A better managed code with modules and components gives us advantage while debugging and triubleshooting for issues and fixing bugs.
  3. Strictly follow MVC's SOC: The Separation of Concern(SOC) is a topic which has been discussed much in detail but still people miss out on them while working on applications. SInce Angular provides a very explicit MVC architecture, with help of controllers, services, directives, config, routes etc. , we should be keeping the task of each component to themselves.
  4. Avoid explicit digest cycles: Avoid using $digest() or $apply() method explicitly as they trigger a new digest cycle. Digest cycles evaluate all the scope variable for change in value i.e. dirty checking which in turn may trigger a sequence of digest cycles which is cost intensive in terms of app performance.
  5. Avoid using $watch: Watchers monitor change in values and can be costly for app performance.
  6. Use angular's wrapper over DOM objects: Use angular's wrappers $window, $document, $timeout, $interval etc. instead of window, document, setTimeOut, setInterval . This avoids explicit need of angular digest cycle to be called to apply changed scope values.
  7. Use services to share values across controllers: Avoid using $watch, $rootScope to share values across controllers. The impact of using $watch is mentioned in point above. Using $rootScope is like using a global variable across the app and should not be polluted.
  8. Keep controllers as thin as possible: Controllers represent the viewmodel for the view and should be kept as thin as possible.
  9. Move business logic and data fetching logic to services: Retrieving data and storing data should be moved to skeleton services. Since controllers are plugged/unplugged based on route changes, they should not hold persistent data.
  10. Use ui-router instead of ng-router: Since ui-router depicts the actual hierarchical structure of an app and it also retains the parent view data while navigating to sub-view. This allows for a smooth transition between parent and child views.