AngularJS Best Practices: Directory Structure

We spend a lot of time writing code. In the early phases of a project, the directory structure doesn't matter too much and many people tend to ignore best practices. In the short term, this allows the developer to code rapidly, but in the long term will affect code maintainability. AngularJS is still relatively new and developers are still figuring out what works and doesn't. There are many great ways to structure an app and we'll borrow some principles from existing mature frameworks but also do some things that are specific to Angular.

In this article, I will cover best practices regarding directory structures for both small and large AngularJS apps. This may be a hot button issue with some developers and while there is no "perfect" way to structure an app, I will be writing from experience and lessons learned from projects I've worked on.

Standard Structure

First of all, let's go over what not to do. Many AngularJS tutorials show an app structure that resembles the code below:

This is a very typical app structure that I see. On the surface, it seems to make a lot of sense and is very similar to a lot of MVC frameworks. We have a separation of concerns, controllers have their own folder, views have their own folder, external libraries have their own folder, etc.

The main problem with this directory structure is not apparent when you are working with only a handful of views and controllers. In fact, it is preferable to follow this approach when writing a tutorial for example or for smaller application. This structure makes it very easy for the reader to visualize and conceptualize the concepts you are covering.

This approach falls apart, however, when you start adding additional functionality to the app. Once you have more than 10 controllers, views and directives, you are going to have to do a lot of scrolling in your directory tree to find the required files.

For example, say you are building a blog with Angular. You decide that you would like to add the author information to the bottom of each article. Well now, you have to find the blog directive, controller, potentially the service and finally the view before you can even look at the whole picture and start making edits.

Say a few months down the line, you are adding additional features to your blog and want to rename a particular feature, again it's a hunt throughout the directory structure to find the affected files, edit them, make sure they are all in sync, and then make the changes.

A Better Structure and Foundation

Let's get to best practices and what you should be doing to build scalable and maintainable AngularJS apps that your coworkers will love you for. An ideal AngularJS app structure should be modularized into very specific functions. We also want to take advantage of the wonderful AngularJS directives to further compartmentalize our apps. Take a look at a sample directory structure below:

This directory structure is much harder to read and understand from the get go. A newcomer to Angular may be completely turned off by this complex approach, and that is why you see tutorials and examples in Angular following the simpler directory structure found in examples earlier. Let's dive into the directory structure above and see what's going on here.

index.html

The index.html lives at the root of front-end structure. The index.html file will primarily handle loading in all the libraries and Angular elements.

Assets Folder

The assets folder is also pretty standard. It will contain all the assets needed for your app that are not related your AngularJS code. There are many great ways to organize this directory but they are out of scope for this article. The example above is good enough for most apps.

App Folder

This is where the meat of your AngularJS app will live. We have two subfolders in here and a couple JavaScript files at the root of the folder. The app.module.js file will handle the setup of your app, load in AngularJS dependencies and so on. The app.route.js file will handle all the routes and the route configuration. After that we have two subfolders - components and shared. Let's dive into those next.

Components Folder

The components folder will contain the actual sections for your Angular app. These will be the static views ,directives and services for that specific section of the site (think an admin users section, gallery creation section, etc). Each page should have it's own subfolder with it's own controller, services, and HTML files.

Each component here will resemble a mini-MVC application by having a view, controller and potentially services file(s). If the component has multiple related views, it may be a good idea to further separate these files into 'views', 'controllers', 'services' subfolders.

This can be seen as the simpler folder structure shown earlier in this article, just broken down into sections. So you could essentially think of this as multiple mini Angular applications inside of your giant Angular application.

Shared Folder

The shared folder will contain the individual features that your app will have. These features will ideally be directives that you will want to reuse on multiple pages.

Features such as article posts, user comments, sliders, and others should be crafted as AngularJS Directives. Each component here should have it's own subfolder that contains the directive JavaScript file and the template HTML file.

In some instances, a directive may have it's own services JavaScript file, and in the case that it does it should also go into this subfolder.

This allows us to have definitive components for our site so that a slider will be a slider across the site. You would probably want to build it so that you could pass in options to extend it. For example, you could have:

Now this slider is accessible from any part of our site so we're not reinventing the wheel. We also just have to change it in one place, the shared folder and it will update sitewide.

Best Practices (For Huuuuge Apps)

If you are developing a really large application in AngularJS, you will want to go even further and modularize your app. Here are some additional tips on how to accomplish this.

Modularize the Header and Footer

A good practice here would be to create a Core subfolder under components, and then a subfolder for the Header and Footer and any additional components that will be shared across many pages.

Modularize the Routes

In the structure above we didn't do this, but another good practice for very large apps is to separate the routes into separate files. For example you might add a blogRoutes.js file in the /views/blog/ subfolder and there include only the routes relevant to the blog such as /blog/:slug, /blog/:slug/edit, blog/tags:/tags, etc.

Don't Forget to Minify

If you do decide to opt in and build your AngularJS apps in a modularized fashion, be sure to concatenate and minify your code before going into production. There are many great extensions for both Grunt and Gulp that will help with this - so don't be afraid to split code up as much as you need.

You may not want to necessarily have just one giant .js file for your entire app, but concatenating your app into a few logical files like:

app.js (for app initialization, config and routing)

services.js (for all the services)

This will be greatly beneficial for reducing initial load times of your app.

Keep the Names Consistent

This is more of a general tip, but this will save you a headache in the future, when writing components and you need multiple files for the component, try to name them in a consistent pattern. For example, blogView.html, blogServices.js, blogController.js.

Benefits of the Modularized Approach

The example above shows a modularized approach to building AngularJS. The benefits of this approach include:

Code Maintainability

Follow the approach above will logically compartmentalize your apps and you will easily be able to locate and edit code.

Scalable

Your code will be much easier to scale. Adding new directives and pages will not add bloat to existing folders. Onboarding new developers should also be much easier once the structure is explained. Additionally, with this approach, you will be able to drop features in and out of your app with relative ease so testing new functionality or removing it should be a breeze.

Debugging

Debugging your code will be much easier with this modularized approach to app development. It will be easier to find the offending pieces of code and fix them.

Testing

In Conclusion

To conclude, this article covered some of the best practices in regards to structuring an AngularJS app. It is easy to ignore good practices in order to save time upfront. We all have a tendency to just want to start writing code. Sometimes this passion can hurt us in the long run when our awesome apps grow and become popular and then we're stuck rewriting or even worse maintaining badly thought out code. I hope this article had some helpful tips.

I plan on building a barebones AngularJS application structure that should follow the best practices outlined in this article that will help you get started building Angular apps quickly and efficiently. Keep a lookout for that in the coming weeks. Stay tuned for Part 2 where we put these concepts into practice!