Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
AngularJS Deployment Essentials
AngularJS Deployment Essentials

AngularJS Deployment Essentials:

eBook
$9.99 $16.99
Paperback
$26.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

AngularJS Deployment Essentials

Chapter 1. Our App and Tool Stack

Before NASA or Space X launches a vessel into the cosmos, there is a tremendous amount of planning and preparation involved. The guiding principle when planning for any successful mission is similar to minimizing efforts and resources while retaining maximum return on the mission. Our principles for development and deployment are no exception to this axiom, and you will gain a firmer working knowledge of how to do so in this chapter.

In this chapter, you will learn how to do the following:

  • Minimize efforts and maximize results using a tool stack optimized for AngularJS development
  • Access the krakn app via GitHub for deployment in future chapters
  • Scaffold an Angular app with Yeoman, Grunt, and Bower
  • Set up a local Node.js development server
  • Read through krakn's source code

The right tools for the job

Web applications can be compared to buildings; without tools, neither would be a pleasure to build. This makes tools an indispensable factor in both development and construction. When tools are combined, they form a workflow that can be repeated across any project built with the same stack, facilitating the practices of design, development, and deployment. The argument can be made that it is just as paramount to document workflow as an application's source code or API.

Along with grouping tools into categories based on the phases of building applications, it is also useful to group tools based on the opinions of a respective project—in our case, Angular, Ionic, and Firebase. I call tools grouped into opinionated workflows tool stacks. For example, the remainder of this chapter discusses the tool stack used to build the application that we will deploy across environments in this book. In contrast, if you were to build a Ruby on Rails application, the tool stack would be completely different because the project's opinions are different. Our app is called krakn, and it functions as a real-time chat application built on top of the opinions of Angular, the Ionic Framework, and Firebase.

Tip

You can find all of krakn's source code at github.com/zachmoreno/krakn.

Version control with Git and GitHub

Git is a command-line interface (CLI) developed by Linus Torvalds, to use on the famed Linux kernel. Git is mostly popular due to its distributed architecture making it nearly impossible for corruption to occur. Git's distributed architecture means that any remote repository has all of the same information as your local repository. It is useful to think of Git as a free insurance policy for my code.

Version control with Git and GitHub

You will need to install Git using the instructions provided at www.git-scm.com/book/en/Getting-Started-Installing-Git for your development workstation's operating system.

www.GitHub.com has played a notable role in Git's popularization, turning its functionality into a social network focused on open source code contributions. With a pricing model that incentivizes Open Source contributions and licensing for private, GitHub elevated the use of Git to heights never seen before.

If you don't already have an account on GitHub, now is the perfect time to visit www.github.com to provision a free account. I mentioned earlier that krakn's code is available for forking at www.github.com/zachmoreno/krakn. This means that any person with a GitHub account has the ability to view my version of krakn, and clone a copy of their own for further modifications or contributions. In GitHub's web application, forking manifests itself as a button located to the right of the repository's title, which in this case is ZachMoreno/krakn. When you click on the button, you will see an animation that simulates the hardcore forking action. This results in a cloned repository under your account that will have a title to the tune of YourName/krakn.

Node.js

Node.js, commonly known as Node, is a community-driven server environment built on Google Chrome's V8 JavaScript runtime that is entirely event driven and facilitates a nonblocking I/O model. According to www.nodejs.org, it is best suited for:

"Data-intensive real-time applications that run across distributed devices."

So what does all this boil down to? Node empowers web developers to write JavaScript both on the client and server with bidirectional real-time I/O. The advent of Node has empowered developers to take their skills from the client to the server, evolving from frontend to full stack (like a caterpillar evolving into a butterfly). Not only do these skills facilitate a pay increase, they also advance the Web towards the same functionality as the traditional desktop or native application.

For our purposes, we use Node as a tool; a tool to build real-time applications in the fewest number of keystrokes, videos watched, and words read as possible. Node is, in fact, a modular tool through its extensible package interface, called Node Package Manager (NPM). You will use NPM as a means to install the remainder of our tool stack.

NPM

The NPM is a means to install Node packages on your local or remote server. NPM is how we will install the majority of the tools and software used in this book. This is achieved by running the $ npm install –g [PackageName] command in your command line or terminal. To search the full list of Node packages, visit www.npmjs.org or run $ npm search [Search Term] in your command line or terminal as shown in the following screenshot:

NPM

Yeoman's workflow

Yeoman is a CLI that is the glue that holds your tools into your opinionated workflow. Although the term opinionated might sound off-putting, you must first consider the wisdom and experience of the developers and community before you who maintain Yeoman. In this context, opinionated means a little more than a collection of the best practices that are all aimed at improving your developer's experience of building static websites, single page applications, and everything in between. Opinionated does not mean that you are locked into what someone else feels is best for you, nor does it mean that you must strictly adhere to the opinions or best practices included. Yeoman is general enough to help you build nearly anything for the Web as well as improving your workflow while developing it. The tools that make up Yeoman's workflow are Yo, Grunt.js, Bower, and a few others that are more-or-less optional, but are probably worth your time.

Yo

Apart from having one of the hippest namespaces, Yo is a powerful code generator that is intelligent enough to scaffold most sites and applications. By default, instantiating a yo command assumes that you mean to scaffold something at a project level, but yo can also be scoped more granularly by means of sub-generators. For example, the command for instantiating a new vanilla Angular project is as follows:

$ yo angular radicalApp

Yo will not finish your request until you provide some further information about your desired Angular project. This is achieved by asking you a series of relevant questions, and based on your answers, yo will scaffold a familiar application folder/file structure, along with all the boilerplate code. Note that if you have worked with the angular-seed project, then the Angular application that yo generates will look very familiar to you. Once you have an Angular app scaffolded, you can begin using sub-generator commands. The following command scaffolds a new route, radicalRoute, within radicalApp:

$ yo angular:route radicalRoute

The :route sub-generator is a very powerful command, as it automates all of the following key tasks:

  • It creates a new file, radicalApp/scripts/controllers/radicalRoute.js, that contains the controller logic for the radicalRoute view
  • It creates another new file, radicalApp/views/radicalRoute.html, that contains the associated view markup and directives
  • Lastly, it adds an additional route within, radicalApp/scripts/app.js, that connects the view to the controller

Additionally, the sub-generators for yo angular include the following:

:controller
:directive
:filter
:service
:provider
:factory
:value
:constant
:decorator
:view

All the sub-generators allow you to execute finer detailed commands for scaffolding smaller components when compared to :route, which executes a combination of sub-generators.

Installing Yo

Within your workstation's terminal or command-line application type, insert the following command, followed by a return:

$ npm install -g yo

Tip

If you are a Linux or Mac user, you might want to prefix the command with sudo, as follows:

$ sudo npm install –g yo

Grunt

Grunt.js is a task runner that enhances your existing and/or Yeoman's workflow by automating repetitive tasks. Each time you generate a new project with yo, it creates a /Gruntfile.js file that wires up all of the curated tasks. You might have noticed that installing Yo also installs all of Yo's dependencies. Reading through /Gruntfile.js should incite a fair amount of awe, as it gives you a snapshot of what is going on under the hood of Yeoman's curated Grunt tasks and its dependencies.

Generating a vanilla Angular app produces a /Gruntfile.js file, as it is responsible for performing the following tasks:

  • It defines where Yo places Bower packages, which is covered in the next section
  • It defines the path where the grunt build command places the production-ready code
  • It initializes the watch task to run:
    • JSHint when JavaScript files are saved
    • Karma's test runner when JavaScript files are saved
    • Compass when SCSS or SASS files are saved
    • The saved /Gruntfile.js file
  • It initializes LiveReload when any HTML or CSS files are saved
  • It configures the grunt server command to run a Node.js server on localhost:9000, or to show test results on localhost:9001
  • It autoprefixes CSS rules on LiveReload and grunt build
  • It renames files for optimizing browser caching
  • It configures the grunt build command to minify images, SVG, HTML, and CSS files or to safely minify Angular files

Let us pause for a moment to reflect on the amount of time it would take to find, learn, and implement each dependency into our existing workflow for each project we undertake. Ok, we should now have a greater appreciation for Yeoman and its community.

For the vast majority of the time, you will likely only use a few Grunt commands, which include the following:

$ grunt server
$ grunt test
$ grunt build

Bower

If Yo scaffolds our application's structure and files, and Grunt automates repetitive tasks for us, then what does Bower bring to the party? Bower is web development's missing package manager. Its functionality parallels that of Ruby Gems for the Ruby on Rails MVC framework, but is not limited to any single framework or technology stack. The explicit use of Bower is not required by the Yeoman workflow, but as I mentioned previously, the use of Bower is configured automatically for you in your project's /Gruntfile.js file.

How does managing packages improve our development workflow? With all of the time we've been spending in our command lines and terminals, it is handy to have the ability to automate the management of third-party dependencies within our application. This ability manifests itself in a few simple commands, the most ubiquitous being the following command:

$ bower install [PackageName] --save

With this command, Bower will automate the following steps:

  1. First, search its packages for the specified package name
  2. Download the latest stable version of the package if found
  3. Move the package to the location defined in your project's /Gruntfile.js file, typically a folder named /bower_components
  4. Insert dependencies in the form of <link> elements for CSS files in the document's <head> element, and <script> elements for JavaScript files right above the document's closing </body> tag, to the package's files within your project's /index.html file

This process is one that web developers are more than familiar with because adding a JavaScript library or new dependency happens multiple times within every project. Bower speeds up our existing manual process through automation and improves it by providing the latest stable version of a package and then notifying us of an update if one is available. This last part, "notifying us of an update if … available", is important because as a web developer advances from one project to the next, it is easy to overlook keeping dependencies as up to date as possible. This is achieved by running the following command:

$ bower update

This command returns all the available updates, if available, and will go through the same process of inserting new references where applicable.

Bower.io includes all of the documentation on how to use Bower to its fullest potential along with the ability to search through all of the available Bower packages.

Tip

Searching for available Bower packages can also be achieved by running the following command:

$ bower search [SearchTerm]

If you cannot find the specific dependency for which you search, and the project is on GitHub, consider contributing a bower.json file to the project's root and inviting the owner to register it by running the following command:

$ bower register [ThePackageName] [GitEndpoint]

Registration allows you to install your dependency by running the next command:

$ bower install [ThePackageName]

The Ionic framework

The Ionic framework is a truly remarkable advancement in bridging the gap between web applications and native mobile applications. In some ways, Ionic parallels Yeoman where it assembles tools that were already available to developers into a neat package, and structures a workflow around them, inherently improving our experience as developers.

If Ionic is analogous to Yeoman, then what are the tools that make up Ionic's workflow? The tools that, when combined, make Ionic noteworthy are Apache Cordova, Angular, Ionic's suite of Angular directives, and Ionic's mobile UI framework.

Batarang

An invaluable piece to our Angular tool stack is the Google Chrome Developer Tools extension, Batarang, by Brian Ford. Batarang adds a third-party panel (on the right-hand side of Console) to DevTools that facilitates Angular's specific inspection in the event of debugging. We can view data in the scopes of each model, analyze each expression's performance, and view a beautiful visualization of service dependencies all from within Batarang. Because Angular augments the DOM with ng- attributes, it also provides a Properties pane within the Elements panel, to inspect the models attached to a given element's scope. The extension is easy to install from either the Chrome Web Store or the project's GitHub repository and inspection can be enabled by performing the following steps:

  1. Firstly, open the Chrome Developer Tools.
  2. You should then navigate to the AngularJS panel.
  3. Finally, select the Enable checkbox on the far right tab.

Your active Chrome tab will then be reloaded automatically, and the AngularJS panel will begin populating the inspection data. In addition, you can leverage the Angular pane with the Elements panel to view Angular-specific properties at an elemental level, and observe the $scope variable from within the Console panel.

Sublime Text and Editor integration

While developing any Angular app, it is helpful to augment our workflow further with Angular-specific syntax completion, snippets, go to definition, and quick panel search in the form of a Sublime Text package. Perform the following steps:

  1. If you haven't installed Sublime Text already, you need to first install Package Control. Otherwise, continue with the next step.
  2. Once installed, press command + Shift + P in Sublime.
  3. Then, you need to select the Package Control: Install Package option.
  4. Finally, type angularjs and press Enter on your keyboard.

In addition to support within Sublime, Angular enhancements exist for lots of popular editors, including WebStorm, Coda, and TextMate.

Krakn

As a quick refresher, krakn was constructed using all of the tools that are covered in this chapter. These include Git, GitHub, Node.js, NPM, Yeoman's workflow, Yo, Grunt, Bower, Batarang, and Sublime Text. The application builds on Angular, Firebase, the Ionic Framework, and a few other minor dependencies.

The workflow I used to develop krakn went something like the following. Follow these steps to achieve the same thing. Note that you can skip the remainder of this section if you'd like to get straight to the deployment action, and feel free to rename things where necessary.

Setting up Git and GitHub

The workflow I followed while developing krakn begins with initializing our local Git repository and connecting it to our remote master repository on GitHub. In order to install and set up both, perform the following steps:

  1. Firstly, install all the tool stack dependencies, and create a folder called krakn.
  2. Following this, run $ git init, and you will create a README.md file.
  3. You should then run $ git add README.md and commit README.md to the local master branch.
  4. You then need to create a new remote repository on GitHub called ZachMoreno/krakn.
  5. Following this, run the following command:
    $ git remote add origin git@github.com:[YourGitHubUserName] /krakn.git
    
  6. Conclude the setup by running $ git push –u origin master.

Scaffolding the app with Yo

Scaffolding our app couldn't be easier with the yo ionic generator. To do this, perform the following steps:

  1. Firstly, install Yo by running $ npm install -g yo.
  2. After this, install generator-ionicjs by running $ npm install -g generator-ionicjs.
  3. To conclude the scaffolding of your application, run the yo ionic command.

Development

After scaffolding the folder structure and boilerplate code, our workflow advances to the development phase, which is encompassed in the following steps:

  1. To begin, run grunt server.
  2. You are now in a position to make changes, for example, these being deletions or additions.
  3. Once these are saved, LiveReload will automatically reload your browser.
  4. You can then review the changes in the browser.
  5. Repeat steps 2-4 until you are ready to advance to the predeployment phase.

Views, controllers, and routes

Being a simple chat application, krakn has only a handful of views/routes. They are login, chat, account, menu, and about. The menu view is present in all the other views in the form of an off-canvas menu.

The login view

The default view/route/controller is named login. The login view utilizes the Firebase's Simple Login feature to authenticate users before proceeding to the rest of the application. Apart from logging into krakn, users can register a new account by entering their desired credentials. An interesting part of the login view is the use of the ng-show directive to toggle the second password field if the user selects the register button. However, the ng-model directive is the first step here, as it is used to pass the input text from the view to the controller and ultimately, the Firebase Simple Login. Other than the Angular magic, this view uses the ion-view directive, grid, and buttons that are all core to Ionic.

Each view within an Ionic app is wrapped within an ion-view directive that contains a title attribute as follows:

<ion-view title="Login">

The login view uses the standard input elements that contain a ng-model attribute to bind the input's value back to the controller's $scope as follows:

  <input type="text" placeholder="you@email.com" ng-model="data.email" />

  <input type="password" placeholder= "embody strength" ng-model="data.pass" />

  <input type="password" placeholder= "embody strength" ng-model="data.confirm" />

The Log In and Register buttons call their respective functions using the ng-click attribute, with the value set to the function's name as follows:

  <button class="button button-block button-positive" ng-click="login()" ng-hide="createMode">Log In</button>

The Register and Cancel buttons set the value of $scope.createMode to true or false to show or hide the correct buttons for either action:

  <button class="button button-block button-calm" ng-click="createMode = true" ng-hide="createMode">Register</button>
  <button class="button button-block button-calm" ng-show="createMode" ng-click= "createAccount()">Create Account</button>

  <button class="button button-block button-assertive" ng-show="createMode" ng-click="createMode =     false">Cancel</button>

$scope.err is displayed only when you want to show the feedback to the user:

  <p ng-show="err" class="assertive text-center">{{err}}</p>

</ion-view>

The login controller is dependent on Firebase's loginService module and Angular's core $location module:

controller('LoginCtrl', ['$scope', 'loginService', '$location',
  function($scope, loginService, $location) {

Ionic's directives tend to create isolated scopes, so it was useful here to wrap our controller's variables within a $scope.data object to avoid issues within the isolated scope as follows:

    $scope.data = {
      "email"   : null,
      "pass"   : null,
      "confirm"  : null,
      "createMode" : false
    }

The login() function easily checks the credentials before authentication and sends feedback to the user if needed:

    $scope.login = function(cb) {
      $scope.err = null;
      if( !$scope.data.email ) {
        $scope.err = 'Please enter an email address';
      }
      else if( !$scope.data.pass ) {
        $scope.err = 'Please enter a password';
      }

If the credentials are sound, we send them to Firebase for authentication, and when we receive a success callback, we route the user to the chat view using $location.path() as follows:

      else {
        loginService.login($scope.data.email, $scope.data.pass, function(err, user) {
         $scope.err = err? err + '' : null;
         if( !err ) {
          cb && cb(user);
          $location.path('krakn/chat');
         }
       });
      }
    };

The createAccount() function works in much the same way as login(), except that it ensures that the users don't already exist before adding them to your Firebase and logging them in:

    $scope.createAccount = function() {
      $scope.err = null;
      if( assertValidLoginAttempt() ) {
       loginService.createAccount($scope.data.email, $scope.data.pass,
         function(err, user) {
          if( err ) {
            $scope.err = err? err + '' : null;
          }
          else {
            // must be logged in before I can write to my profile
            $scope.login(function() {
             loginService.createProfile(user.uid, user.email);
             $location.path('krakn/account');
            });
          }
         });
      }
    };

The assertValidLoginAttempt() function is a function used to ensure that no errors are received through the account creation and authentication flows:

    function assertValidLoginAttempt() {
      if( !$scope.data.email ) {
       $scope.err = 'Please enter an email address';
      }
      else if( !$scope.data.pass ) {
       $scope.err = 'Please enter a password';
      }
      else if( $scope.data.pass !== $scope.data.confirm ) {
       $scope.err = 'Passwords do not match';
      }
      return !$scope.err;
    }
   }])

The chat view

Keeping vegan practices aside, the meat and potatoes of krakn's functionality lives within the chat view/controller/route. The design is similar to most SMS clients, with the input in the footer of the view and messages listed chronologically in the main content area. The ng-repeat directive is used to display a message every time a message is added to the messages collection in Firebase. If you submit a message successfully, unsuccessfully, or without any text, feedback is provided via the placeholder attribute of the message input.

There are two filters being utilized within the chat view: orderByPriority and timeAgo. The orderByPriority filter is defined within the firebase module that uses the Firebase object IDs that ensure objects are always chronological.

Tip

The timeAgo filter is an open source Angular module that I found. You can access it at www.jsfiddle.net/i_woody/cnL5T/.

The ion-view directive is used once again to contain our chat view:

<ion-view title="Chat">

Our list of messages is composed using the ion-list and ion-item directives, in addition to a couple of key attributes. The ion-list directive gives us some nice interactive controls using the option-buttons and can-swipe attributes. This results in each list item being swipeable to the left, revealing our option-buttons as follows:

  <ion-list option-buttons="itemButtons" can-swipe= "true" ng-show="messages">

Our workhorse in the chat view is the trusty ng-repeat directive, responsible for persisting our data from Firebase to our service to our controller and into our view and back again:

   <ion-item ng-repeat="message in messages | orderByPriority" item="item" can-swipe="true">

Then, we bind our data into vanilla HTML elements that have some custom styles applied to them:

    <h2 class="user">{{ message.user }}</h2>

The third-party timeago filter converts the time into something such as, "5 min ago", similar to Instagram or Facebook:

    <small class="time">{{ message.receivedTime | timeago }}</small>
    <p class="message">{{ message.text }}</p>
   </ion-item>
  </ion-list>

A vanilla input element is used to accept chat messages from our users. The input data is bound to $scope.data.newMessage for sending data to Firebase and $scope.feedback is used to keep our users informed:

  <input type="text" class="{{ feeling }}" placeholder= "{{ feedback }}" ng-model="data.newMessage" />

When you click on the send/submit button, the addMessage() function sends the message to your Firebase, and adds it to the list of chat messages, in real time:

  <button type="submit" id="chat-send" class="button button-small button-clear" ng-click="addMessage()"><span class="ion-android-send"></span></button>
</ion-view>

The ChatCtrl controller is dependant on a few more modules other than our LoginCtrl, including syncData, $ionicScrollDelegate, $ionicLoading, and $rootScope:

controller('ChatCtrl', ['$scope', 'syncData', '$ionicScrollDelegate', '$ionicLoading', '$rootScope',
   function($scope, syncData, $ionicScrollDelegate, $ionicLoading, $rootScope) {

The userName variable is derived from the authenticated user's e-mail address (saved within the application's $rootScope) by splitting the e-mail and using everything before the @ symbol:

var userEmail = $rootScope.auth.user.e-mail
      userName = userEmail.split('@');

Avoid isolated scope issue in the same fashion, as we did in LoginCtrl:

    $scope.data = {
      newMessage   : null,
      user      : userName[0]
    }

Our view will only contain the latest 20 messages that have been synced from Firebase:

    $scope.messages = syncData('messages', 20);

When a new message is saved/synced, it is added to the bottom of the ng-repeated list, so we use the $ionicScrollDeligate variable to automatically scroll the new message into view on the display as follows:

$ionicScrollDelegate.scrollBottom(true);

Our default chat input placeholder text is something on your mind?:

    $scope.feedback = 'something on your mind?';
    // displays as class on chat input placeholder
    $scope.feeling = 'stable';

If we have a new message and a valid username (shortened), then we can call the $add() function, which syncs the new message to Firebase and our view is as follows:

    $scope.addMessage = function() {
      if(  $scope.data.newMessage
        && $scope.data.user ) {
       // new data elements cannot be synced without adding them to FB Security Rules
       $scope.messages.$add({
                   text    : $scope.data.newMessage,
                   user    : $scope.data.user,
                   receivedTime : Number(new Date())
                 });
       // clean up
       $scope.data.newMessage = null;

On a successful sync, the feedback updates say Done! What's next?, as shown in the following code snippet:

       $scope.feedback = 'Done! What\'s next?';
       $scope.feeling = 'stable';
      }
      else {
       $scope.feedback = 'Please write a message before sending';
       $scope.feeling = 'assertive';
      }
    };

    $ionicScrollDelegate.scrollBottom(true);
])

The account view

The account view allows the logged in users to view their current name and e-mail address along with providing them with the ability to update their password and e-mail address. The input fields interact with Firebase in the same way as the chat view does using the syncData method defined in the firebase module:

<ion-view title="'Account'" left-buttons="leftButtons">

The $scope.user object contains our logged in user's account credentials, and we bind them into our view as follows:

  <p>{{ user.name }}</p>
 …
  <p>{{ user.email }}</p>

The basic account management functionality is provided within this view; so users can update their e-mail address and or password if they choose to, using the following code snippet:

  <input type="password" ng-keypress= "reset()" ng-model="oldpass"/>
 …
  <input type="password" ng-keypress= "reset()" ng-model="newpass"/>
 …
  <input type="password" ng-keypress= "reset()" ng-model="confirm"/>

Both the updatePassword() and updateEmail() functions work in much the same fashion as our createAccount() function within the LoginCtrl controller. They check whether the new e-mail or password is not the same as the old, and if all is well, it syncs them to Firebase and back again:

  <button class="button button-block button-calm" ng-click= "updatePassword()">update password</button>
 …
   <p class="error" ng-show="err">{{err}}</p>
  <p class="good" ng-show="msg">{{msg}}</p>
 …
  <input type="text" ng-keypress="reset()" ng-model="newemail"/>
 …
  <input type="password" ng-keypress="reset()" ng-model="pass"/>
 …
  <button class="button button-block button-calm" ng-click= "updateEmail()">update email</button>
 …
  <p class="error" ng-show="emailerr">{{emailerr}}</p>
  <p class="good" ng-show="emailmsg">{{emailmsg}}</p>
 …
</ion-view>

The menu view

Within krakn/app/scripts/app.js, the menu route is defined as the only abstract state. Because of its abstract state, it can be presented in the app along with the other views by the ion-side-menus directive provided by Ionic. You might have noticed that only two menu options are available before signing into the application and that the rest appear only after authenticating. This is achieved using the ng-show-auth directive on the chat, account, and log out menu items. The majority of the options for Ionic's directives are available through attributes making them simple to use. For example, take a look at the animation="slide-left-right" attribute. You will find Ionic's use of custom attributes within the directives as one of the ways that the Ionic Framework is setting itself apart from other options within this space.

The ion-side-menu directive contains our menu list similarly to the one we previously covered, the ion-view directive, as follows:

<ion-side-menus>
 <ion-pane ion-side-menu-content>
  <ion-nav-bar class="bar-positive">

Our back button is displayed by including the ion-nav-back-button directive within the ion-nav-bar directive:

   <ion-nav-back-button class="button-clear"><i class= "icon ion-chevron-left"></i> Back</ion-nav-back-button>
  </ion-nav-bar>

Animations within Ionic are exposed and used through the animation attribute, which is built atop the ngAnimate module. In this case, we are doing a simple animation that replicates the experience of a native mobile app:

  <ion-nav-view name="menuContent" animation="slide-left-right"></ion-nav-view>
 </ion-pane>

 <ion-side-menu side="left">
  <header class="bar bar-header bar-positive">
   <h1 class="title">Menu</h1>
  </header>
  <ion-content class="has-header">

A simple ion-list directive/element is used to display our navigation items in a vertical list. The ng-show attribute handles the display of menu items before and after a user has authenticated. Before a user logs in, they can access the navigation, but only the About and Log In views are available until after successful authentication.

   <ion-list>
    <ion-item nav-clear menu-close href= "#/app/chat" ng-show-auth="'login'">
     Chat
    </ion-item>

    <ion-item nav-clear menu-close href="#/app/about">
     About
    </ion-item>

    <ion-item nav-clear menu-close href= "#/app/login" ng-show-auth="['logout','error']">
     Log In
    </ion-item>

The Log Out navigation item is only displayed once logged in, and upon a click, it calls the logout() function in addition to navigating to the login view:

    <ion-item nav-clear menu-close href="#/app/login" ng-click= "logout()" ng-show-auth="'login'">
     Log Out
    </ion-item>
   </ion-list>
  </ion-content>
 </ion-side-menu>
</ion-side-menus>

The MenuCtrl controller is the simplest controller in this application, as all it contains is the toggleMenu() and logout() functions:

controller("MenuCtrl", ['$scope', 'loginService', '$location', '$ionicScrollDelegate', function($scope, loginService, $location, $ionicScrollDelegate) {
  $scope.toggleMenu = function() {
   $scope.sideMenuController.toggleLeft();
  };

  $scope.logout = function() {
    loginService.logout();
    $scope.toggleMenu();  };
 }])

The about view

The about view is 100 percent static, and its only real purpose is to present the credits for all the open source projects used in the application.

Global controller constants

All of krakn's controllers share only two dependencies: ionic and ngAnimate. Because Firebase's modules are defined within /app/scripts/app.js, they are available for consumption by all the controllers without the need to define them as dependencies. Therefore, the firebase service's syncData and loginService are available to ChatCtrl and LoginCtrl for use.

The syncData service is how krakn utilizes three-way data binding provided by www.krakn.firebaseio.com. For example, within the ChatCtrl controller, we use syncData( 'messages', 20 ) to bind the latest twenty messages within the messages collection to $scope for consumption by the chat view. Conversely, when a ng-click user clicks the submit button, we write the data to the messages collection by use of the syncData.$add() method inside the $scope.addMessage() function:

$scope.addMessage = function() {
  if(...) { $scope.messages.$add({ ... });
  }
};

Models and services

The model for krakn is www.krakn.firebaseio.com. The services that consume krakn's Firebase API are as follows:

  • The firebase service in krakn/app/scripts/service.firebase.js
  • The login service in krakn/app/scripts/service.login.js
  • The changeEmail service in krakn/app/scripts/changeEmail.firebase.js

The firebase service defines the syncData service that is responsible for routing data bidirectionally between krakn/app/bower_components/angularfire.js and our controllers. Please note that the reason I have not mentioned angularfire.js until this point is that it is basically an abstract data translation layer between firebaseio.com and Angular applications that intend on consuming data as a service.

Models and services

Predeployment

Once the majority of an application's development phase has been completed, at least for the initial launch, it is important to run all of the code through a build process that optimizes the file size through compression of images and minification of text files. This piece of the workflow was not overlooked by Yeoman and is available through the use of the $ grunt build command. As mentioned in the section on Grunt, the /Gruntfile.js file defines where built code is placed once it is optimized for deployment. Yeoman's default location for built code is the /dist folder, which might or might not exist depending on whether you have run the grunt build command before.

Summary

In this chapter, we discussed the tool stack and workflow used to build the app that we will deploy in the forthcoming chapters. Together, Git and Yeoman formed a solid foundation for building krakn. Git and GitHub provided us with distributed version control and a platform for sharing the application's source code with you and the world. Yeoman facilitated the remainder of the workflow: scaffolding with Yo, automation with Grunt, and package management with Bower. With our app fully scaffolded, we were able to build our interface with the directives provided by the Ionic Framework, and wire up the real-time data synchronization forged by our Firebase instance. With a few key tools, we were able to minimize our development time while maximizing our return.

Next, we will take our freshly constructed real-time chat app, krakn, and deploy it to an Apache web server for consumption over the Web. Once manually deployed to Apache, we will discuss automating future deployments and optimizing the environment for an Angular application.

Left arrow icon Right arrow icon

Description

If you are a web developer, this handy guide will empower you to quickly learn the fundamentals of AngularJS development and deployment.

What you will learn

  • Form a bulletproof deployment workflow that can be repeated on future updates
  • Deploy your application as a mobile AngularJS app using the Ionic Framework
  • Build powerful tool stacks that work together to optimize your workflow
  • Employ Grunt to automate repetitive tasks such as image optimization, code minification, and packaging
  • Automatically deploy your application from GitHub.com to your Apache server
  • Configure your production environments to optimally serve your AngularJS applications
  • Scale and enhance your Node.js server using both the Heroku Dashboard and Toolbelt
  • Package your application as a Google Chrome app that can be run online and offline
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Feb 27, 2015
Length: 148 pages
Edition : 1st
Language : English
ISBN-13 : 9781783983582
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Publication date : Feb 27, 2015
Length: 148 pages
Edition : 1st
Language : English
ISBN-13 : 9781783983582
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 81.98
AngularJS Web application development Cookbook
$54.99
AngularJS Deployment Essentials
$26.99
Total $ 81.98 Stars icon
Banner background image

Table of Contents

9 Chapters
1. Our App and Tool Stack Chevron down icon Chevron up icon
2. Deploying to Apache Chevron down icon Chevron up icon
3. Deploying to Heroku Chevron down icon Chevron up icon
4. Deploying to Firebase Hosting Chevron down icon Chevron up icon
5. Deploying a Mobile App Chevron down icon Chevron up icon
6. Deploying as Chrome Apps Chevron down icon Chevron up icon
7. Postdeployment Chevron down icon Chevron up icon
8. Conclusion – AngularJS Deployment Essentials Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
(1 Ratings)
5 star 0%
4 star 0%
3 star 100%
2 star 0%
1 star 0%
Mat Brunt Apr 29, 2015
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
I have mixed feelings about this book. It provides some useful information and an insight on deploying AngularJS applications, but is very strongly focused on a specific subset of tools. That said, you can abstract some of the concepts out to more general environments, which is where I think the author was heading with his examples.It is a tough problem to describe - you will never be able to satisfy everyones setup or deployment requirements. The majority of the content is around setting the tools up rather than best practises, caveats and pitfalls of deployment. I read through each chapter as a traditional book and it felt like a substantial portion of each chapter could be skimmed, if all you were interested in was deployment methodologies.My recommendation would be to cherry pick chapters of the book that are applicable to your environment or the problem you are trying to solve, rather than reading through the book chapter by chapter.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela