The Bet Smart team blogs regularly about the iGaming & Betting Industry, product development, design & user experience, and the latest technology trends.

What I learned building an app with Ionic Framework

Written by on September 11, 2014

Bet Smart was recently tasked with the challenge to deliver a mobile app into a large, well-known sports betting brand (name undisclosed – for now!). We were given the latitude and creative control to determine what that product could be within the constraints of some high-level business objectives. We pitched a few nifty ideas, and they ultimately chose a data-streaming app that engages users as a second-screen companion during in-play soccer matches.

Technology Decisions

After the proposed concept was accepted and signed-off, it was time to craft together a technical requirements doc for the frontend side of development. This meant a lot of R&D with regards to choosing frameworks and build systems. I built a few micro projects testing different generators like yeoman’s angular-cordova-geneator, angular-phonegap-seed, and even took the approach of building a complete bare-bones solution. In the end, I arrived at the Ionic framework which seemed to be the best option for our goals. It provided various components we needed, included angular, sass, cordova wrapper, and provided an easy build system to deploy to both android and iOS via the CLI:

$ ionic build ios

$ ionic build android

Ionic took care of many of those time-consuming tasks needed for mobile web projects such as native-like content scrolling, 300ms delay removal, swipe & tap gestures, cross-device inconsistencies, etc.

That said, it is still beta and there were many pitfalls I stumbled upon. Those issues are not all specific to Ionic. In fact, many are related to the Cordova ecosystem. In this post I hope to shed some light on those issues I came across and how I solved them.

Disclaimer

There may be better solutions to the problems listed below and they may be already resolved; I’m simply stating my experiences and what worked for me. The mobile web is still incredibly hacky and you need to physically cross-test on various devices (not just emulators) to ensure your app performs and works as expected.

Pain Points & Gotchas

Problem: The gulp build system included in Ionic’s starter kit is incomplete for distribution code. When your app is ready for production, you need to concatenate and minify your code to reduce load times and overall app size. This is hugely important for mobile and should be automated, as iterations are frequent.

Solution: I switched to a much more complete build system called ionic-generator which utilizes grunt js instead of gulp. Switching reduced the app from 10mb to 3mb, added support for multiple build environments, and provided js linting, ripple, and more.


Problem: Minified JS was breaking on devices.

Solution: Because it’s next to impossible to debug a concatenated and minified script, I was saved by grunt’s jshint plugin (which is included in the ionic-generator). It turns out that one single missing semicolon broke the entire app. Use a linter — it’ll save your hide.


Problem: Incompatible Google analytics plugins for both platforms on Cordova 3.5.0: danwilson’s google-analytics-plugin, and cmackay’s google-analytics-plugin.

Solution: This plugin works on both Android and iOS for Cordova 3.5.

An aside: That plugin works but there’s a gotcha with iOS: it doesn’t support the arm64 architecture. To fix, you need to remove that value architecture from Build Settings > Architectures > Valid Architectures in XCode. More on this here.


Problem: Android does not clear the app cache (localStorage or saved javascripts) when you build and deploy to your Android device. This results in 11/10 frustration when your latest code is not represented in the build.

Solution: Uninstall your app before you build-and-run.


Problem: Android emulators are slowwww as a snail.

Solution: If you’re going to be testing on an emulator (which I’d recommend against) use the geny motion emulator. It’s very fast!


Problem: Emulators don’t work with Cordova plugins. Neither does ripple for me.

Solution: Don’t use emulators. They’re slow and not representative of an actual real-world experience. Your desktop is likely much faster than your device so you need to be conscious of memory consumption.


Problem: The ionic-generator grunt build system doesn’t install plugins properly for iOS.

Solution: You must manually copy plugins from /plugins/<plugin-name>/src/ios/<files> to /platforms/ios/<project-name>/plugins/<plugin-name>/<files>.


Problem: The network information plugin returns different values for Android devices which are NOT documented. For example, when checking if a device was connected to the Internet, the Galaxy s3 returned 3g instead of CELL_3g which is NOT specified in the documents.

Solution: This is my code to protect against inconsistent connection statuses:

var isOnline = function () {
  var isConnected = false;
  var networkConnection = navigator.connection;
  if (!networkConnection.type) {
    $log.error('networkConnection.type is not defined');
    return false;
  }

  switch (networkConnection.type.toLowerCase()) {
    case 'ethernet':
    case 'wifi':
    case 'cell_2g':
    case 'cell_3g':
    case 'cell_4g':
    case '2g':
    case '3g':
    case '4g':
    case 'cell':
    case 'cellular':
      isConnected = true;
      break;
  }

  $log.log('isOnline? '+ isConnected);
  return isConnected;
};

Problem: Using the Phonegap push plugin wrapped in an angular service, your ecb callback functions are not properly being executed when you attempt to register you device.

Solution: Make sure you have that ecb callback function wrapped in quotes and attached to the global window object if it’s inside a service:

pushNotification.register(apnsSuccessHandler, genericErrorHandler, {
  'badge': 'true',
  'sound': 'true',
  'alert': 'true',
  'ecb': 'window.onNotificationAPN'
});

Tips & Tricks

  • Some of the Angular $log methods don’t work in both Android and iOS consoles: $log.log('hi mom') and $log.error('bye mom') works on both, so stick to those two.
  • Use idevicesyslog for iOS to log to your terminal instead of using XCode’s developer console.
  • Use logcat-color for Android instead of adb logcat. It makes it reading the devices logs much easier and looks good.
  • Test on multiple devices for both iOS and Android. There’s so many inconsistencies in how devices will render your app. Certain plugins don’t work on some devices. DOM is rendered differently on different engines and different versions of engines.
  • Develop as much as you can on your desktop before going to the mobile devices for testing. It’s a slow process to code -> build + run -> test + debug, so get as much done on your local browser first.
  • Which Android resolutions to use for the loading/splash is a bit confusig. I found what worked for me was: LDPI- 320 x 240, MDPI- 480 x 320, HDPI- 800 x 480, XHDPI- 1280 x 720, XXHDPI- 1920 x 1080.
  • Keep DOM to a minimum; when not in a view, you should remove it, not just hide it. This will greatly increase performance on your devices. Ionic now supports this collection repeat directive which only renders DOM which is shown.
  • Limit frequency of updating list data used in ng-repeat. Keep it to a 5-second minimum.
  • Don’t use Angular filters in your ng-repeats if you’re updating that data frequently. Instead attach directives to elements. A perfect example is a countdown clock. Instead of this: Coutdown: {{timestamp | date: 'mm:ss'}} use an angular timer directive <timer end-time="timestamp">{{minutes}}m, {{seconds}}s</timer>.
  • Page-to-page transitions don’t work well across devices. I’d recommend avoiding animations or transitions for best performance.
  • When you transition between pages, Angular has a noticeable delay before any expressions in content are rendered. Better to use an overlay before the content resolves. I used $ionicLoading to show a loading screen before the page finished rendering.
  • If you’re using toggle buttons, e.g.: to turn something on and off and it hits an API endpoint, be sure to wrap that interaction in a timer so you’re not calling that endpoint multiple times if the user decides to tap the control multiple times in quick succession. Wait a second, then hit the endpoint.

Conclusion

Building native-wrapped HTML5 apps is still in its infancy and you won’t get native-like performance. But the pros of deploying to multiple platforms and building / iterating very quickly can outweigh the cons of lesser performance.

I hope the pitfalls I encountered and resolved will benefit other developers taking the same journey I did.

Bet Smart’s Data Feed: Unrestricted, live sports xml. Starting at $149 per month for a limited time! Get A Free Demo
  • Jose

    Hello,

    “Limit frequency of updating list data used in ng-repeat. Keep it to a 5-second minimum.”

    Could you please post an example of this, feels like good advice, but I don’t understand it. didn’t know you could time-limit ng-repeat.

    Cool Article,

  • http://pulakonline.com Pulak

    I have few queries since we are evaluating ionic for our projects. I will post each question at a time.

    Q1. How easy it is to customize any ionic components as per project requirement in both JavaScript and CSS level?

  • http://pulakonline.com Pulak

    Q2. How much overhead ionic components create in terms of DOM, Memory usage?

  • http://pulakonline.com Pulak

    Q3. In case of collection-repeat, say i want to display 10 items out of 1000 items at a time. So at any point in time only say, will there be only 10 divs and will only new data be injected in the previous created divs?

  • http://pulakonline.com Pulak

    Q4. Say, I have selected Ionic for our project but don’t need all the UI or other components in it. So does Ionic gives the flexibility to exclude those components from the framework itself and use the rest?

  • http://pulakonline.com Pulak

    Q5. How easy it is to include an external library into Ionic if required?

  • x0b

    I think what is meant is that if you change the data object used to populate the ng-repeat (for example you might load different data from your server after user interaction) that you shouldn’t do this more than once every 5 seconds.

  • Ramin

    nice

  • Gray Olson

    When you talk about the “gulp build system being incomplete” you make it sound like you think this is the fault of gulp itself and that switching to grunt solves this — in reality, you can easily do all the same things the grunt configuration did by just modifying your gulpfile (the gulp configuration), it’s just not set up for you.

  • http://www.quoterobot.com Jono

    Hey Gary, thanks for the feedback. I miscommunicated the point of that problem. Gulp is not the issue. Gulp is capable, fast, easy to read and quickly gaining traction for good reasons. In my experiences, I found that the gulp build file (Gulpfile.js) bundled with the starter kit was incomplete for production as it did not provide the optimization processes necessary for production code. So yes, you’re correct in stating it’s just not setup for me. It’s a matter of putting in the effort to make your own build system which can be quite time consuming and probably not worth the effort when there’s solid systems available. What we ended up switching to was https://github.com/diegonetto/generator-ionic which turned out to be the a great option.

  • http://www.quoterobot.com Jono

    Thanks for the comments. To elaborate on the issue, we experienced performance issues when data polling every couple seconds and sending that payload to the views which was rendered via ng-repeat. The main performance issue was a noticeable freeze while it re-rendered the dom elements. This was especially bad on devices in the iphone 4 range. This was in part due to using nested ng-repeat’s and complicated data structures. The end solution was breaking our payload into separate objects and doing low-level data comparison to determine what has changed and what to update. So, instead of sending a large payload to the views, break that payload apart into multiple objects and only update what has changed. This hugely improves performance. On that note, it’s worth looking into ionic’s new collection-repeat: http://ionicframework.com/docs/api/directive/collectionRepeat/

  • http://www.quoterobot.com Jono

    Thanks Ramin!

  • http://www.quoterobot.com Jono

    Easy as butter on toast. Check out http://ngcordova.com/docs/ to see some examples of integration cordova plugins into angular services.

  • http://www.quoterobot.com Jono

    Ionic comes bundled into a js file called ionic-angular.js. It might be possible to strip components from the library, but probably not worth your efforts.

  • http://www.quoterobot.com Jono

    As I understand collection-repeat, yes. Elements which are not in the viewport and thrown away which is hugely more performant.

  • http://www.quoterobot.com Jono

    We’ve found our apps consume around 3~10mb in memory, which is an acceptable target for most mobile devices. Be sure to keep a close eye on your developer console (Profiles in chrome) to ensure your app does not have memory leaks or garbage collection issues. This will definitely crash your mobile app if so!

  • http://www.quoterobot.com Jono

    Yep! It’s fairly straight forward to override CSS and customize the visual components. You shouldn’t muck around with any core javascript code as it’s never a wise idea to touch the framework libraries.

  • http://pulakonline.com Pulak

    Thanks buddy for taking your time out and answering all of my queries.

    If possible share your email id/twitter handle/skype so that i can reach you when i have any queries.

  • Jonathan Adami

    Great idea but it sounds like you’re doing React’s job ;)
    http://facebook.github.io/react/

    I’m now wondering if the overhead of having ngReact working with ionic would be worth it… Thanks for this article though, bookmarked ;)

  • chandramuralis

    Thanks for the article…will be definitely useful for new Ionic developers

  • Wes Laney

    Fantastic advice. I have been developing with Ionic for few months and I wish I new some of these tips and tricks. Keep up the good work!!

  • mahami

    Thank you for sharing your experience

  • http://forwebonly.com/ Robin van Baalen

    Great article. Very recognizable. Been there, experienced that. Nice round up of common issues one might encounter when building apps with Ionic.

    I totally agree with you on the “gulp build system being incomplete” part. Not gulp itself but the features they’ve implemented are very limited and not production ready.

  • Matthew Reetz

    I’ve noticed transitions and animations on iOS are smooth, but tend to lag on Android. Has this been your experience?

  • Zyad Sherif

    I’ve encountered a problem that is very specific to Ionic while developing my app.

    Native apps usually have a storyboard or something to define the relation between different views, in ionic/angular there is the ui-router state, my app is similar to twitter using the tabular template, each tab has its own navigation stack but there is no way to have the same state present in all tabs like for example the tweet view or user profile view.

    The state has to be explicitly attached to a tab stack when configuring the app states, I ended up creating 4 different states to the same view/controller for each tab in the application.

  • http://pl.linkedin.com/in/rafjanicki bl4de

    Hi Jon,

    Thanks for this post, I’d like to aks about one thing I didn’t find here.

    I assume you’ve got a lot of data in your application. Being aware of Ionic/Angular problem with a lot of $scope properties checked in every $digest loop – did you experience any performance issues related to two-way data binding?

    If yes, how did you resolve them?
    We are thinking about one time binding ( {{::property}} ) but it provides another problem with refreshing data, so for now it might be some workaround, but definitely it won’t be a final solution.

    We are building an application (Cordova+Ionic, for Samsung tablet with Android only – there won’t be any other devices running this application) and we’ve already experienced some of problems you’re writing about (eg. problem with not-so-smooth-as-we-want-to horizontal scrolling and so on).

    Thank you for any advice. I know it’s been a while when you wrote this post, but unfortunately (even after three months) most of issues still occurs :)

    Regards,

    Rafal, Poland

  • http://www.quoterobot.com Jono

    We experienced similar issues with older android devices. The safest bet is to conditionally disable page transitions for android devices. I believe chromeview was introduced kitkat+, which hugely improved performance: https://developer.android.com/guide/webapps/migrating.html

  • http://www.quoterobot.com Jono

    Hey Rafal,

    Thanks for the comments. We did experience some lag issues when sending a large payload to the views. See me comments below to Jose: http://www.betsmartmedia.com/what-i-learned-building-an-app-with-ionic-framework#comment-1719417587

    If you can manage to break your parent data structure into smaller structures and do some low-level comparison to only update what changes, it will safeguard against those freeze issues you’re experiencing. Let me know if you’d like more information on the matter.

    Best,

    Jon

  • http://pl.linkedin.com/in/rafjanicki bl4de

    Hi Jon,

    Thanks for response.

    We definitely have to break our data into smaller parts (we’ll implement infinitive scroll and add data only when user will scroll particular view), however I was wondering what will happen if we reach $scope maximum performance (regardless render issues).

  • http://www.marcfalk.com marcfalk

    Have you had a chance to revisit Ionic on Android after Crosswalk became available with Cordova?

  • Burak

    Wow, these are brilliant informations man!

  • Albert Chang

    Thank you so much Jon. You have actually inspired me to do my own write-up of a competitive Hybrid Mobile App framework — AppGyver Supersonic, which has its set of gotchas and quirks as well.

    Question: Are you guys still using Ionic? If so, how much of the aforementioned issues have been resolved?

  • Albert Chang

    Hi Zyad. I’m trying to understand your last paragraph. Can you elaborate on what you meant by “creating 4 different statues to the same view/controller…”? I’m assuming you didn’t create child sub-states for each parent state?

  • Albert Chang

    Hey Marc. Are you using Ionic presently? If so, curious what issues you have/are coming across?

  • http://www.marcfalk.com marcfalk

    I’m currently using Ionic, developing an app like Tinder (for a niche). Ionic itself is a bliss, and you’ll quickly pick up the idea, concepts etc. However, I do struggle with performance optimization for Android, and will have to look into this e.g. making sure Crosswalk is used etc. Besides that, I haven’t really had issues as such.

  • Albert Chang

    Niiice. I can see the need for ensuring a super smooth, and super fast UI experience. I’m already picking up ionic fairly quickly (thanks to being dedicated to angular for 1 year && my previous experience with a similar hybrid mobile framework). I may look into integrating React into my angular codebase; but that will depend on how beneficial ‘collection-repeat’ and bind-once will be.

  • Zyad Sherif

    Let me elaborate, since am using the tab navigation system each tab has its own nav stack, and take for example a Twitter app there a state for a tweet that is basically the same everywhere, in ionic if I need it to be visible in all four or 5 tabs I need to have 4 or more different states for the same view and controller so that its a sub from the specific Tab which makes navigation impossible since I have to put the state name that is appropriate for the stack am in.

    I ended up routing to it manually using a function that checks which parent state am in and routes to the corresponding state name, the routes file looks miserable having to have duplicates just so serve each tab stack, and had to do that for two other views like the profile for example.

    Did I explain myself?

  • Albert Chang

    So I gave Ionic a shot over the past week, and have come to realize that — much like this blog — there are gotchas even for things that should have been solved 3-ish years ago…

    Here is the link to the forum entry that has caused me to discontinue using Ionic, and leave JS altogether when it comes to mobile development:

    http://forum.ionicframework.com/t/100-proposal-window-cordova-ios-emulator/20915/11

    In short, I offered anyone $100 to help me resolve 2 features that should easily be considered vital/baseline features of the framework. Yet, like the bazillion other users that experienced the same issue, these problems could not be resolved in slam-dunk fashion, nor even resolved at all.

    I am an Angular 1.x developer of a full year, and have been developing with one of Ionic’s competitors, AppGyver, for about 10 months. One would think getting an emulator to work would be easy-peezy…

  • http://ferrisutanto.com Ferri Sutanto

    Thanks for all your summary, really helpful :D

  • Jess Patton

    If you ever want to give ionic another try, use the intel xdk! it comes with built in emulator, a debugging tool for on device debugging, brackets as a built in text editor, tons of starting templates including ionic and reactjs, and a build tab where you can upload your app to an intel build server and then simple download it when it is done. You can find it here – https://software.intel.com/en-us/html5/tools

  • jorisw

    Problem: The Android emulator is slow as hell

    Solution: Select a x86 CPU in the Android Virtual Device manager (try different phones to emulate until the CPU dropdown shows x86), and install HAX so your PC/Mac uses the same instruction sets. It will run blazing fast. http://www.developer.com/ws/android/development-tools/haxm-speeds-up-the-android-emulator.html

  • gabriel troia

    Hey Zyad, did you solve your problem in a more elegant way, yet? Having a similar problem I ended up not using the tabs at all, but to simulate them by reseting the history when clicked on a tab link.

    I’m wondering if you came up with a better solution…

  • xasx

    srdvsdvdf

  • xasx

    xffv d