AngularJS Architecture

Who's this?

 

 

 

Sergio Cruz

Developer at @codeschool

Twitter: @hashtagserg

GitHub: sergiocruz

More: sergiocruz.me

Who is this talk for?

  • Anyone writing Angular apps in 2015
  • Beginners and advanced users alike
  • Specially those working in teams
  • Writing larger codebase apps
  • Longer-term applications

This talk will:

  • Get you thinking
  • Introduce you to topics that can get deep
  • Be a conversation starter

This talk is not:

  • Have all definite solutions
  • Include an answer to all life's questions

disclosure:

The suggestions provided here will not fit all your projects

Take the ones you see fit, but do keep an open mind

Scaffolding your app

Tip 1: Single codebase

Don't share the codebase

with your backend repo

Why have a single code base?

  • No compromises on app scaffolding
  • Easy test environment & CI Integration

Tip 2: Directory organization

Group by feature

Group by features

BAD

Group by features

BETTER

Group by features

BEST

Tip 3: Team Consistency

Let's scale apps at development time

John Papa's Angular style guide

  • Angular best practices
  • Recommended by Angular Team for future upgrades

Style guides mean nothing

unless they're followed

  • Great static analysis tools:
  • Leverage tooling
    • Good: in text editor
    • Better: in build process (using gulp, grunt etc)

Other team related tips

  • Help team members grow
  • Diversify tasks
  • Keep low friction level
  • Be a good team player :)

Tip 4: Use a build system

grunt, gulp, npm, make, etc.

Pick a task runner (grunt, gulp etc):

Tip 5: Use a module loader

Node-like feel when coding

for the browser

  • plugs right into task runners
  • npm install anything
  • require() calls
  • no more globals (for the most part)

Coding

your app

Tip 1: Angular Modules

A feature-based modules are

a good idea

One module per directory

  • One directory per feature right?
  • Each directory should be its own module
// heroes/heroes-ctrl.js

angular
  .module('heroesApp.users')
  .controller('HeroesCtrl', HeroesCtrl);

function HeroesCtrl() {
  // superhero code goes here
}

Bonus: Easy to open source

  • Example: you wrote a cool set of reusable directives
  • Your code now is:
    • In the same module & directory
    • Put the code in its own repo
    • Publish to NPM
  • Users will add your submodule as a dependency
    to their projects

Tip 2: HTTP only in services

Endpoints change often while in development

Protect yo self!

// heroes-ctrl.js

angular
  .module('heroesApp.users')
  .controller('HeroesCtrl', [
    '$http',
    HeroesCtrl
  );

function HeroesCtrl($http) {

  var vm = this;
  vm.getHeroes = getHeroes;
  vm.heroes = [];

  function getHeroes() {
    $http.get('/heroes')
      .then(function(heroes) {
        vm.heroes = heroes;
      });
  }

}
// users-ctrl.js

angular
  .module('heroesApp.users')
  .controller('UsersCtrl', [
    '$http',
    UsersCtrl
  );

function UsersCtrl($http) {

  var vm = this;
  vm.getHeroes = getHeroes;
  vm.heroes = [];

  function getHeroes() {
    $http.get('/heroes')
      .then(function(heroes) {
        vm.heroes = heroes;
      });
  }

}
// heroes-api.js

angular
  .module('heroesApp')
  .factory('HeroesAPI', [
    '$http',
    HeroesFactory
  );

function HeroesFactory($http) {

  function getHeroes() {
    return $http.get('/heroes');
  }

  return {
    getHeroes: getHeroes
  };

}
// heroes-ctrl.js

angular
  .module('heroesApp.heroes')
  .controller('HeroesAPI', [
    'HeroesAPI',
    HeroesCtrl
  );

function HeroesCtrl(HeroesAPI) {
  var vm = this;
  vm.getHeroes = getHeroes;
  vm.heroes = [];

  function getHeroes() {
    HeroesAPI
      .getHeroes()
      .then(function(heroes) {
        vm.heroes = heroes;
      });
  }

}

Why?

When endpoints change,
update one file.

Even better

Use a library like Restangular

Tip 3: Beware of Performance

Small oversights can cost a lot on the long run

Performance tips

  • Stay on angular's latest version
  • Use track-by on ng-repeats
  • Use one-time bindings
  • Cache critical template files
  • `ng-events` means more digest cycles
    • Be cautious with use things like `ng-mouseover`
    • Don't be afraid of using jQuery events in performance intensive tasks, and notifying Angular at the end

Don't optimize prematurely

Be wise and know that today's problems are different than tomorrow's problems. Solve today's problems first.

Tip 4: Write in ES2015

Write tomorrow's JavaScript today with transpiliers like babel

Babel

  • Plugs right into module loaders
  • Transpiles human readable code to ES5
  • Supports ES2015 (and some ES2016 features)

Moving away from
angular.module

Instead let's import services that
do not rely on Angular

// heroes/heroes-ctrl.js

import angular from 'angular';
import heroes from './heroes';

angular
  .module('heroesApp.heroes')
  .controller('HeroesCtrl', HeroesCtrl);

function HeroesCtrl() {

  let vm = this;
  vm.heroes = heroes;
  
}
// heroes/heroes.js

let heroes = [
  'Captain America',
  'Iron Man',
  'Spider Man'
];

export default heroes;

Moving away from `angular.module` for services

Why? Because Stark said so.

jk lol... because now we get to use `heroes.js` outside of an Angular 1.x environment.

I can haz Universal JavaScript?

class HeroSquad {

  constructor(HeroesAPI) {
    this.HeroesAPI = HeroesAPI;
  }

  getHeroes() {
    this.HeroesAPI
      .getList()
      .then(function() {
        // do something
      });
  }
}

Stick to functions when writing controllers

function HeroSquad(HeroesAPI) {

  let vm = this;
  vm.getHeroes = getHeroes;
    

  function getHeroes() {
    HeroesAPI
      .getList()
      .then(function() {
        // do something
      });
  }
}

Why?

Because everything we injected gets attached to this, exposing them to the view.

No privates in js :(

Even better: TypeScript

  • >= v1.5 has feature parity with ES2015
  • Adds type checks to your code
  • Angular 2 is written in TypeScript

Tip 5: Angular 2 in mind

Angular 2 is still in its alpha version, but will be out soon

Design with components in mind

What does this mean?

  • More directives
  • Slimmer controllers
  • Avoid $scope, prefer vanilla JS
  • Follow previous steps mentioned here :)

Thanks for watching!

Follow me: @hashtagserg

“The secret to building large apps is not to build large apps. Build smaller apps and fit the pieces together”

- John Papa

AngularJS Architecture

By Sergio Cruz

AngularJS Architecture

Wondering what are the best practices for writing an Angular App in 2015? This talk will touch a few points that will help you write a kick-butt Angular 1.x app.

  • 1,400