Actually Building a Large AngularJS App at Scale

Patterns that emerge as your AngularJS app grows

I’m Hunter, Co-founder and Lead Front-End Engineer of a product-focused marketing automation startup called Landing Lion.

Landing Lion was founded in January 2015 by myself, Alan Pledger, and Craig McCown. The three of us met while studying at Georgia Tech and have been building products on the web together for over half a decade. Craig focuses on the back-end (i.e. database, RESTful API, etc.) while I handle the front-end — aka pretty colors and slick animations.

The Front-End Stack

Landing Lion’s customer-facing app is an AngularJS web application that communicates with its web servers over a RESTful API using HTTPS.

Here is a breakdown of the core technologies in the web app:

Core Web Technologies: HTML, JS, CSS.

CSS Extension: We use Sass (the other popular options here are less and scss).

JavaScript Frameworks: Our core framework is AngularJS. I use d3js for information visualization within our reporting.

JavaScript Packages: We use lodash for basic JavaScript utility functions (i.e. sorting an array) and GreenSock for animations, like fading in a modal when it opens.

JavaScript Build Tools: We use Grunt for running development tasks, executing environment builds, and targeting deployments at a given environment. We use Yeoman to scaffold dependencies in our index.html — it basically just allows us to put “if/else” statements around our html’s source files. We use npm to include 3rd party JavaScript packages, such as our core JavaScript frameworks and packages. Express is used with node for local web development (i.e. spinning-up a web-server on localhost port 9000).

JavaScript Test Tools: We test our application with a combination of Karma and Jasmine. Karma is used to run and execute tests we implement with Jasmine.

Landing Lion Loves AngularJS

Our core JavaScript framework of choice is AngularJS, otherwise known as ng1 (specifically version 1.3.2). Yep, you read correctly. Even though Angular 2 & 4 are available we still use Angular 1 within Landing Lion’s main web application.

I started with AngularJS early in its alpha versions. It was around version 0.3. Currently, I have been working with AngularJS for half a decade. At the time public opinion held AngularJS as unproven and untested — everyone debated its scalability.

“Every line written by us, every file created by us”

If you have a history with web development, then you know how rapidly the scene changes. Half a decade is a big commitment to a single JavaScript framework. Common practice is to hop on the next trend — bouncing from Ember to Knockout to AngularJS to React to Angular 2 to whatever is next.

I Love AngularJS

I have yet to find a good reason to switch to a different framework. This is the result of a simple philosophy I believe: the best way to master anything is through hard work and dedication.

This means you must push yourself consistently every day. How can you master a JavaScript framework? Simple: do not switch unless you must. It does not matter how hard you work. If you continue bouncing around frameworks for anecdotal reasons or because its what everyone else is doing then you are missing the second requirement to mastery: dedication.

Because I follow this philosophy, the goal of my content will never be an attempt to sway people from their chosen framework towards AngularJS. Nor is it a stage for me to boast about the size or complexity of Landing Lion’s web application. I hope this content will serve as a resource for developers of all skill levels to learn and grow.

Okay, Now Some of Our Numbers

Disclaimer: I do not believe that any of these numbers, big or small, can ever correlate to the quality of the product. A high-quality product can have thousands of lines, millions of lines, or even billions of lines.

Currently, Landing Lion has roughly 150,000 lines of JavaScript spread across 500 JavaScript files. This number does not include 3rd party dependencies. In the next post, I will cover how we organize and name all 500 of our JavaScript files in Landing Lion as well as the rest of our 1250+ HTML, CSS and other miscellaneous files — none of which are 3rd party.

In total, 8,032 git commits have been made to Landing Lion web application. For reference, the AngularJS project on GitHub has 7,507 (as of writing this).

“We love when members of the web development community are transparent. We believe transparency can drive progress.”

Below are some cumulative numbers that overview our AngularJS app for Landing Lion. Inline recipe declarations, such as an inline directive controller, are not included to avoid inflation.

45 Modules

Modules 238 Factories

Factories 243 Directives

Directives 73 Controllers

Controllers 28 Providers

Providers 91 Services

Services 12 Filters

Filters 11 Animations

Organizing Files in Large Apps

Within the forums and communities I frequent, I will often stumble upon someone asking for an example of large AngularJS application. If there is a response to his request, then it is likely a link to an open source project, such as angular bootstrap or angular ui-router. While it is a nice gesture that someone took the time to answer his question, and even though open source projects are totally awesome, I have learned through experience that some patterns will only emerge out of necessity. Most of the time, that necessity comes hand-in-hand with the need to scale.

When I google “AngularJS at scale” the first thing that comes up is this presentation, titled “Building LARGE Apps with AngularJS” by Jason Dobry. Jason covers a lot of topics in his presentation, but I only want to touch on one, “File Organization”. It overviews how you should be organizing your files within a “LARGE” AngularJS app. This is what he suggests:

orders/

directives/

orders.html

ordersDirective.js

services/

orderService.js

users/

directives/

users.html

usersDirective.js

services/

userService.js

home/

controllers/

home.html

homeController.js

login.html

loginController.js

shared/

services/

i18nService.js

filters/

i18nFilter.js

App.js

This type of file organization is commonly known in the Angular community as “Organize by feature”. Ignoring the quality of the rest of the presentation and knowing we have tried countless file organization variations on a file structure that is roughly 100 times as large, I am confident this “File Organization” is not the optimal solution for scale. This might be hard to believe for some. The majority of AngularJS at scale tutorials published advocate for the same file structure.

When I first started with AngularJS I organized our files into directories almost identical to Jason’s example. Over time, however, I diverged from “Organizing by feature”, because there are issues that emerge as your application grows that this organization scheme is incapable of suppressing. I am not arguing “Organize by feature” is wrong. It works — and at a certain size (like Jason’s example) it is probably better than the file organization scheme we settled on. I am arguing, however, that when you are working with a large AngularJS web application it is less efficient than the strategy we ended up with after a gob of iterations.

Through experience, our team has found putting HTML files and JavaScript files in the same directory will eventually become hard to manage; this goes for CSS files as well. When your application is the size of Jason’s, “Organizing by feature” is arguably more efficient; however, when you are dealing with hundreds of states and thousands of HTML files, new issues arise that you have to consider.

“Organizing by feature” makes it difficult to reuse HTML, directives, services, and factories across feature directories — which is ironic to me because reusability is one of the major selling points of AngularJS. Also, I have found it takes a longer time to locate a specific JavaScript file in a directory that has dozens of HTML and JavaScript files versus one with only JavaScript files.

Focusing solely on file organization I would make the following changes to Jason’s example (changes are bold):

orders/

+ views/

+ orders.html

directives/

- orders.html

ordersDirective.js

services/

orderService.js

users/

+ views/

+ users.html

directives/

- users.html

usersDirective.js

services/

userService.js

home/

+ views/

+ home.html

+ login.html

controllers/

- home.html

homeController.js

- login.html

loginController.js

shared/

services/

i18nService.js

filters/

i18nFilter.js

App.js

A good rule to follow: Ensure each directory only contains files with the same file extension (i.e. “.js” or “.html”). Over time, you will have hundreds, maybe even thousands, of files. Having files with different file extensions can get messy quick. It may appear to be an insignificant detail, but semantics matter when you are trying to squeeze every bit of efficiency out of your development workflow.

There are always exceptions, but in general, I stick to this rule.

I will dive more into file organization with the next post where I will cover the patterns Landing Lion uses for file organization and file naming.

What is next?

There is plenty of published content that helps beginners with Angular’s steep learning curve. Most of it is great content. I am eternally grateful to John Lindquist (johnlindquist) for his amazing tutorials at egghead.io. They were essential when I was getting started with AngularJS five years ago. I’m certain this is still true, his work is quality.

The Angular community needs content to help developers get comfortable with the fundamentals (like AngularJS’s digest cycle and dependency injection). Unfortunately, there is not enough content that discusses the complications that arise when building a large AngularJS application. I want to help the community by producing content that details the patterns I have settled on after countless refactors and iterations.

I hope this content can help other web developers building AngularJS apps. I also hope it motivates other Angular developers with similar projects to share their knowledge and experiences.

I love when members of the web development community are transparent. I believe transparency can drive progress. I hope this content will inspire other developers to be transparent so we can all learn from one another.

Let’s learn together —

If you wanna see what I’m up too 🌖