HOw to build Hybrid apps that don't


SUCK


Using Phonegap / Angularjs

Who AM I?

Jamie Sutherland

 jamie@mallzee.com - @wedgybo
CTO @ Mallzee

Why should you listen to me?

You probably shouldn't.

I talk a lot of nonsense and the reason this talk exists is due to my stubbornness

 of sticking with this stack even when things got tough. 

Think you can do a better job. Get in touch with me 

we're hiring :)

hybrid apps are


  • Built with web technologies HTML5/JS
  • Mixed with native components and APIs
  • Not web apps
  • A great prototyping tool - MVP
  • Difficult to get towards native quality

phonegap/cordova


Tools to create hybrid apps

Provides JS APIs to native APIs via Plugins


Gets a bad rep because its seen at limited and the majority of apps are slow and clunky
(Ours included. Until now. By now I mean the one waiting to be released)

It's only limited by it's lack of Plugins and effort applied
(maybe some memory limitations in their too)

Should i build a hybrid app?


of course!

unless you have the following


Lots of images on screen at once 
(Memory limits) 
Copious complex animations 
(Older phone limitations, JANK)
A talent for building native apps and know nothing about web development 
(why are you here?)

Using phonegap

npm install -g phonegap 
Creating your first app
phonegap create edinburghjs com.edinburghjs.meetup EdinburghJS  
Adding platforms
phonegap platform add ios 
supported platforms: ios, android, blackberry, windows phone 7/8, FirefoxOS, fireos
How to install plugins
phonegap local plugin add https://github.com/mallzee/phonegap-facebook-plugin.git 
Contacts, Network-Information, Splashscreen, StatusTap, FacebookConnect, Camera, Geolocation, FileAPI, Vibration, PushNotifications, and many more

AngularJS

Use yeoman - yeoman.io
npm install -g yo 
Angular generator
npm install -g generator-angular 
Create a project
yo angular edinburghjs 
Install PhoneGap grunt tasks
npm install grunt-angular-phonegap

BASICS


Single Page Application (SPA)

Avoid external calls for view markup
If you must, cache it and check for new versions on the app startup

Avoid displaying large quantities of images at one time


VIEWs


Avoid complex DOM
If it's crazy, you're probably doing it wrong



 

Devices

Multiple platforms/screen sizes?
phonegap local plugins add https://github.com/apache/cordova-plugin-device 
Set the device type on the rootScope
function setDeviceType() {

  var model = device.model; // device is injected by the phonegap plugin

  if (model.match(/iPhone/) || model.match(/iPod/)) {    $rootScope.device = 'mobile';  } else if (model.match(/iPad/)) {    $rootScope.device = 'tablet';  }} 
ng-if and ng-switch are your friend add DOM when required
<div ng-if="device == 'tablet'">[ADD MORE STUFF IN HERE]</div>

Layout & CSS


Modern browsers. Modern CSS. flexbox

Minimise paint & style recalculations. 60FPS FTMFW!

Avoid box-shadow, opacity on older devices

Use classList instead of addClass

Add items to the GPU if they are moving. But not too much!
.movingItem { transform: translateZ(0); }

$ANIMATE

Animate your DOM elements with ease from css
.product.ng-enter,
.product.ng-leave {
  -webkit-transition:0.5s ease all;
  -moz-transition:0.5s ease all;
  -o-transition:0.5s ease all;
  transition:0.5s ease all;
}

.product.ng-enter,
.product.ng-leave.ng-leave-active {
  opacity: 0;
}

.product.ng-leave,
.product.ng-enter.ng-enter-active {
  opacity: 1;
}
$animate.enter(element, parent, sibling, callback) 

DATA

Minimise external calls 
Multiple HTTP calls are expensive 

Group data if possible
You built the API? Awesome, create private endpoints to make your app snappier

Cache external data in localStorage
Always display cached data first then merge in new data when it becomes available

CACHE Merge

api.query(q, function (products) {
  // Merge updates and remove
  _.each(userProducts, function (p) {
    var found = _.find(products.records, {'_id': p._id});
    _.remove(products.records, {'_id': p._id});
    if (found) {
      _.merge(p, found);
    } else {
      p.__remove = true;
    }
    page++;
  });
  _.remove(userProducts, {'__remove': true});
  _.each(products.records, function (newProduct) {
    userProducts.push(newProduct);
  });
  localStorage.setItem('user.products', userProducts);
});

Stops a complete redraw of the list
Try animating a cache swap and you'll see why

PERFORMANCE TIPS

chrome timeline

Performance tips


batarang




PERFORMANCE TIPS


BINDONCE

Watches = (contacts.length * 2) + 1
<div class="friends">
  <a class="friend" ng-repeat="contact in contacts">
    <h2 ng-bind="contact.name"></h2>
    <img ng-src="contact.profile_image_url" />
  </a>
</div>
Watches = 1
<div class="friends">
  <a class="friend" bindonce ng-repeat="contact in contacts">
    <h2 bo-text="contact.name"></h2>
    <img bo-src="contact.profile_image_url" />
  </a>
</div>

Performance hogs

Functions: Bad

<button ng-class="{'active': !productsFilter.isEmpty()}" ng-click="$state.go('filters')"></button>

functions: good

THEY ARE NOT. Avoid at all costs.
 Write the result to a variable on the scope
<button ng-class="{'active': !productFilter.empty}" ng-click="$state.go('filters')"></button>
productFilter.empty = false;function updateFilter() { // Workout if the filters empty when and changes are made ... empty = (filter.length > 0);}

PERFORMANCE HOGS


Filters: Bad

<div class="price" ng-bind="product.price | currency:'£'"></div>

Filters: Good

Avoid filters in the view. Use $filter on your data
<div class="price" ng-bind="product.price"></div>

Mangle the data in your service/controller
angular.foEach(products, function(product) {  product.price = $filter('currency')(product.price, '£');}

PERFORMANCE HOGS

ngRepeat

Watches can get out of hand quickly

Convenience leads to poor performance

Alternatives



(shameless plug)

MEMORY LEAKS


Angular directives makes it easy to create memory (DOM/Event) leaks

$destroy everything
scope.$on('$destroy', function () {
   item.element.remove();   item.off('click');
 });

angular modules

bower packages

angular-touch
angular-animate
angular-motion
angular-ui-utils
angular-ui-router
angular-strap
angular-carousel
angular-bindonce
angular-local-storage
angular-ui-table-view
restangular

Grunt tasks

 
jshint
less/sass
concat
usemin
imagemin
cssmin
htmlmin
uglyfy
ngmin
html2js

Awesome stuff to look @


Ionic Framework - http://ionicframework.com/

GREAT PHONEGAP APPS

Version 1.4.0 > :D

And I'm spent

Thanks for listening


PASS Me A BEER PLEASE :D


Direct all your love/abuse to me on twitter @wedgybo

Hybrid apps with Phonegap/AngularJS

By Jamie Sutherland

Hybrid apps with Phonegap/AngularJS

Hints and tips on how to create hybrid apps that don't suck with Phonegap/AngularJS.

  • 7,089