Angular is one of the most popular JavaScript frameworks available today. An open source web application framework with an active community around it and built under design principles that support scalability, maintainability and modularization as its core.
Since some time ago in DevWise we have been developing with Angular; both front-ends web and mobile. During these developments we had to accept that unlike some other JavaScript frameworks, Angular requires to do things in a particular way and we have experimented with different methods and rules to organize and structure the source codes. We have also found that as the projects have grown, we have had to adopt new practices, and finally, we have adopted some guidelines and best practices well suited to all types of projects.
Let's go through some of best practices, because there is no perfect way to build an app, but it can always be better.
Files naming convention
Define a way and pursue it with the same obsession that Lebron James follows the ball. Naming conventions help provide a consistent way to find content by just taking a look and should simply help you find your code faster and make it easier to understand. It provides a consistent way to quickly identify and reference components, and provides pattern matching for any automated tasks. In short, it makes your life easier.
So, use consistent names for all components, always following a pattern. If you have a product-list folder inside that folder the files must follow the same format. Good examples are: product-list-controller.js or product-list-service.js, a bad example is productListController.js.
Suffixes for your files
Although this depends a lot on your way to work with large projects, it may be beneficial to add suffixes to the file types you work with, for example, product-list.ctrl.js, product-list-svc.js, etc. This provides an easier way to read the files, and makes it simple to search within any code editor or tools like grunt, gulp, webpack, etc.
Single responsibility
This rule is simple: define 1 component per file.
Each project file has to have an unique responsibility, regardless of the number of lines you may have. Each responsibility must encapsulate and isolate codes to avoid spaghetti codes. Although, initially, we are tempted to unify several features with the excuse that there are few lines, it is very important to start to separate the code from the beginning.
Organize your files by functionality rather than file type
If files were organised into folders determined by their type instead, quite often you find that files need to reference each other by longer paths, and as a developer, you will often find yourself thinking about parallel folder paths.
Instead of having a Controller folder and adding within it all of your controllers, create folders according to your application functionality. Do you have a module that lists products? Create a Product-list folder and within it the controllers, services, directives and everything within your module: Javascript files, HTML and CSS too.
Separate your app modules
Separators help define modules and their submodule hierarchy. For example, if you have an initial module called superProducts that defines your entire application, each functionality must be created as a standalone module superProducts.product-list, depending on your main application.
Directives should be reusable
You must not create directives just because. A good question before you start creating a directive would be “Can I use it in another application?” If the answer is yes, great, go on! But always taking into account not to break this rule: any directive must operate independently of the application that use it.
Lose the fear to Node.js, and automate all
Node.js has many modules that make our life easier and faster. Instead of manually download the libraries that work normally, use bower or npm and simplify your work.
IIFE: Immediately Invoked Function Expression
An IIFE removes variables from the global scope. So, this is a great practice to package the components in functions that are invoked immediately. It helps prevent variables and function declarations from living longer than expected in the global scope, while avoiding possible collisions between variables.