9 Common errors when programming Ionic
Introduce
Ionic, launched two years ago, is an excellent toolkit for developing hybrid applications based on AngularJS . Ionic is currently very popular with app store up to millions of numbers with a strong community with thousands of developers.
Ionic is not new. Meanwhile, web technology and optimization tools are changing rapidly every day. Therefore, it is not easy to decide the direction for a new project. Under such conditions, developers can make mistakes and affect the quality of the application or team performance.
Hopefully with the common errors below, you will be able to avoid the basics and increase the performance and scale of applications when using Ionic.
Common error # 1: Forgot to activate Native Scrolling
Native Scrolling Allows Ionic to identify event scrolls on supported webview. We can create Pull to Refresh , List Reordering and Infinite Scroll (permanent scroll) without JavaScript scrolling (we only need JavaScript scrolling when the browser lacks standard scroll events) .
On android, since Ionic version 1.2 (December 2015), native scrolling is enabled by default. Native scrolling has significantly improved performance and UX, making scrolling smoother thanks to asynchronous events.
Unfortunately, due to the lack of a standard event, native scrolling is not supported on the iOS platform yet.
If you are using the previous version 1.2, you can turn on Native Scrolling on Android by using $ ionicConfigProvider
1 2 | // Enable Native Scrolling on Android $ ionicConfigProvider.platform.android.scrolling.jsScrolling (false); |
You can also turn on and off Native scrolling on every page using the overflow-scroll that navigates every content :
1 2 | <! - Disable Native Scrolling on this page only -> <ion-content overflow-scroll = "false"> |
Remember, unfortunately, the repeat-collection (which allows applications to display lists with multiple titles) has not been supported by native scrolling yet.
Common errors # 2: Do not use Ionic CLI to install Platform and Plugin
Ionic CLI adds many features to the Cordova CLI . Plafrorm and persistence plugin are one of those features.
However, with Cordova CLI, your platform and plugin are only installed on your own system. And when working as a team, you'll want to share the environment, platform and plugin to avoid bugs. Also with the Cordova CLI, it is difficult to synchronize projects between multiple systems. Of course, you can also commit platform and plugin folders, but we do not recommend this method.
When using Ionic CLI to install platform ionic platform add ios and ionic plugin add camera plugins , package.json file will be edited properly.
Platforms and plugins are stored in cordovaPlatforms and cordovaPlugins properties :
1 2 3 4 5 6 7 8 9 | "cordovaPlugins": [ "cordova-plugin-whitelist@1.0.0", "cordova-plugin-inappbrowser@1.0.1", "cordova-plugin-splashscreen@2.1.0" ], "cordovaPlatforms": [ "android", "ios" ] |
Now, other developers have synchronized more easily when creating new code, simply running ionic state restore when needed (adding, deleting or uploading versions)
Common mistake # 3: Thinking Performance Comes out of the Box
Ionic is based on AngularJS, and the performance on the device is still unknown. At this point, I assure you: with just a little AngularJS knowledge, you can build a great application with Ionic.
A good example is the Sworkit app (built with Ionic) with over 9 million users, 7 million downloads and 4.5 stars on Google Play.
If you want to make the most of AngularJS, you need to know some of the following before starting the project.
$ watch
With the scope change in AngularJS, there are generally 4 types of $ watch : $ watch (normal) , $ watch (deep) , $ watchCollection and $ watchGroup .
Each type is different, and choosing the right type can change performance significantly.
$ watch (normal)
Using $ watch normal will only check for existing Object properties, or Item Arrays. Shallow changes (such as adding an Object attribute or inserting an item into an Array) will not be supported.
1 2 3 4 5 | $ scope. $ watch ('watchExpression', function (newVal, oldVal) { if (newVal) { // watchExpression has changed. } }); |
$ watch (deep)
$ watch deep will make shallow and deep changes, such as Nested Object function. With $ watch deep, you will definitely not miss any changes. However, use caution because $ watch deep can change performance.
1 2 3 4 5 | $ scope. $ watch ('watchExpression', function (newVal, oldVal) { if (newVal) { // watchExpression has changed. } }, true); |
$ watchCollection
Consider using $ watchCollection between $ watch normal and $ watch deep . $ watchCollection can also compare object references, and can even weave watches of object properties by adding Object properties or pushing new items into Array.
1 2 3 4 5 | $ scope. $ watchCollection ('watchExpression', function (newVal, oldVal) { if (newVal) { // watchExpression has changed. } }); |
$ watchGroup
Introduced at AngularJS 1.3, $ watchGroup allows tracking multiple expressions at once.
While it is not possible to improve application performance like $ watch normal, $ watchGroup can track multiple scopre expressions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $ scope. $ watchGroup ([ 'watchExpression', 'watchExpression2', 'watchExpression3' ], function (newVals, oldVals) { if (newVals [0]) { // watchExpression has changed. } if (newVals [1]) { // watchExpression2 has changed. } if (newVals [2]) { // watchExpression3 has changed. } }); |
Track By
track by is used to avoid redundant DOM operations when using ng-repeat . If digest cycle finds at least one change element in the collection, ng-repeat will render every element again. Because DOM manipulation always affects application performance, the more we restrict it, the better.
The track by can be considered a special filter, allowing us to update the required elements without having to render the collection again.
1 2 3 4 5 | <! - if items have a unique id -> <div ng-repeat = "item in items track by item.id"> </div> <! - if not, you can use the $ index that theo lại thêm vào mỗi của nó Items -> <div ng-repeat = "user in users track by $ index"> </div> |
Just remember, avoid using track by on the collection-repeat .
One-Time Binding
One-time binding (or : 🙂 was introduced from Angular 1.3, which greatly improved application performance.
Basically, using one-time binding :: on an expression will remove that expression from the list of $ watchers when overloaded. Synonymous with the expression cannot be updated even if the data changes.
1 | <p> {{:: user.firstName}} </p> |
Our advice is to check the app to see if it is up-to-date, somewhat out-of-date, and one-time binding :: that's right. This phase will minimize the burden on digest cycle.
Remember, one-time binding cannot be used in repeat-collection , because the list item on the screen changes when scrolling.
And if you want to learn more about AngularJS and Ionic, I think you should read this Ultimate AngularJS and Ionic performance cheat sheet .
Common error # 4: Logical View Cache awareness is ambiguous
The page application will not default to the page cache. So when using AngularJS, you must have encountered the status of scrolling and input without being saved when you browse to or back between pages.
With Ionic, ten pages will be cached by default, and you can change this feature across the system or on each platform.
1 2 3 4 5 6 | // Globally $ ionicConfigProvider.views.maxCache (5); // Per platforms $ ionicConfigProvider.platform.android.views.maxCache (5); $ ionicConfigProvider.platform.ios.views.maxCache (5); |
Although the page cache may be a bit confusing for a new person, this is still a nice feature.
The problem is that if the user returns to the cached page, the controller will not be re-initialized as in AngularJS applications.
With conditions like this, how will you update the data on the page?
Introducing controller life cycle events
Compared to AngularJS, Ionic offers more life events:
1 2 3 4 5 6 7 8 | $ scope. $ on ('$ ionicView.loaded', function () {}); $ scope. $ on ('$ ionicView.unloaded', function () {}); $ scope. $ on ('$ ionicView.enter', function () {}); $ scope. $ on ('$ ionicView.leave', function () {}); $ scope. $ on ('$ ionicView.beforeEnter', function () {}); $ scope. $ on ('$ ionicView.beforeLeave', function () {}); $ scope. $ on ('$ ionicView.afterEnter', function () {}); $ scope. $ on ('$ ionicView.afterLeave', function () {}); |
These events are necessary if you want to control the view cache.
For example, the event $ ionicView.loaded will be activated as soon as the view is loaded. If this view is cached, this event will no longer be activated, even if the user returns. This is usually the event you will use to boot the variable like event $ viewContentLoaded in AngularJS.
If you want to fetch data each time you access the view (cached or not), you can use the event $ ionicView.enter .
When using the right event at the right time, you can improve the usability of the application.
As for performance, using cache view only affects the size of the DOM. When the page is cached, all viewers will be disconnected and the page will move to the DOM to wait for reuse.
Although the size of the DOM will significantly affect performance, the ten-page cache is still acceptable (depending on the load content of the page, of course).
Common mistake # 5: Unknown about Crosswalk for Android
Each Android version runs a different WebView (application-running browser). Performance will be different from each device, and especially bad on older Android devices. You can install Crosswalk to have the same smooth experience on any Android device. Crosswalk will add the latest Chromium browser to your application (20MB per APK, both with ARM and X86).
Crosswalk can be installed only by using Ionic CLI or Cordova CLI:
1 | ionic plugin add cordova-plugin-crosswalk-webview |
Common error # 6: Try to run the Cordova Plugin in your browser
Most developers using Ionic will want their application to run on iOS and Andoid. After adding platform ionic platform add ios android and some ionic plugins add cordova-plugin-device-orientation cordova-plugin-contacts plugin , many people think they can test on the browser, this is a elementary error because not submit Any browser can apply this method.
Cordova plugin is designed to communicate with native API devices via JavaScript. Communication plugins or device-oriented plugins will therefore only work on one device.
However, you can easily test the code on the device and remotely debug the computer.
Remote debugging on Android
Connect the device, make sure the device is recognized by the computer with the adb devices command (you need the Android SDK).
Build the app and install it on the device with the command ionic run android . When the device starts the application, use Chrome dev tools to open the console (on the computer) chrome: // inspect / # devices , and check the device.
Remote debugging on iOS
Connect the device, make sure the device is recognized by the computer. Build the app and install it on the device with the command ionic run ios -device.
When the application is started, click Develop> Your iPhone> Your app to open Safari dev tools (on your computer):
Run the Cordova Plugin in the browser
Running the Cordova plugin in the browser is a premium feature you should know. From Ionic 1.2, the browser has been officially supported, opening the era of cross-platform applications beyond iOS and Android.
With the Cordova Browser platform, Electron and Web technologies (JavaScript, HTML, and CSS), we can now build Ionic applications for browsers and desktops (Windows, Linux and OSX)
You can find the starter kit on Github .
1 | cordova platform add browser |
Your application needs to be re-compiled before being used correctly as on iOS or Andoid:
1 | cordova run browser |
This command will compile the application and open the default browser.
Cross-platform plugin
Many plugins such as Network, Camera and Facebook support both iOS, Android, and Platform Browser at the same time – all with the same API.
You can know whether the device is online or offline on every platform (iOS, Android, Browser and Desktop) using ngCordova API:
1 2 3 4 5 6 7 8 9 | // listen for Online event $ rootScope. $ on ('$ cordovaNetwork: online', (event, connectionType) => { this.isOnline = true; }); // listen for Offline event $ rootScope. $ on ('$ cordovaNetwork: offline', (event, connectionType) => { this.isOnline = false; }); |
Now, you've probably thought about creating products that run anywhere with just one code base.
Common error # 7: Follow the Starter Kit structure with large-scale applications
When using ionic start myapp, a newly created project will follow the following folder structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | www / js / app.js controllers / aaa.js bbb.js ccc.js services / xxx.js yyy.js zzz.js templates / aaa.html bbb.html ccc.html |
This is called the Folder-by-Type structure. With this structure, JavaScript, CSS, and HTML files will be grouped in style. This structure looks easy for new people, but you will soon lose control when the scale is too large.
A few reasons for not using the Folder-by-Type structure:
- The file number in the folder may become too large
- With a specific feature. It will be hard to find all the files you need to adjust
- Working with a feature will lead to too many open folders
- The bigger the application, the harder it is to work
For large-scale applications, I recommend using the Folders-by-Feature structure, JavaScript, CSS, and HTML files that will now be grouped by feature or AngularJS module:
1 2 3 4 5 6 7 | myNewFeature / index.js (AngularJS module) config.js service.js controller.js index.html style.scss |
Reasons for using Folder-by-Feature structure:
- The number of files in the folder is limited
- Easy to find all files when you need to adjust a feature (because in the same folder)
- You can work independently with a feature
- Easy to know what the module shows (just need to know the folder name is enough)
- Easy to create new features, just copy / paste an existing feature is done
This structure is similar to the default Folders-by-Component structure in Angular2 / Ionic2 applications.
Common error # 8: Constraint with event, and forget requestAnimationFrame
This error is probably the most influential error on performance, and is often seen only in new people. Preview:
1 2 3 4 5 6 7 8 9 10 | <ion-content on-scroll = "getScrollPosition ()"> // ... </ion-content> $ scope.getScrollPosition = function () { // heavy processing, like manipulating DOM // or anything that triggers a $ digest () // will be called every ~ 80ms, // and will impact UX } |
Although Ionic controls these actions, the process may still be too slow. In general, anything that activates the digest loop should be postponed, and should not be activated at the same time as heavy images (also the result of scrolling).
Instead of binding to scroll events, and especially animations, developers can use other methods. As requestAnimationFrame .
1 2 3 4 5 6 7 8 9 | var myElement = document.getElementById ('content'); var elemOffsetFromParent = myElement.offsetTop; onCapturedFrame () {function { if (window.scrollY> = elemOffsetFromParent) { customTweenFunction (myElement, options); } window.requestAnimationFrame (onCapturedFrame); } onCapturedFrame (); |
The above code is just a simple example. The code checks whether the user scrolls through the element header. If you want to apply this example, remember to add vendor-specific alternatives to ensure compatibility across multiple browsers. Depending on the browser, the application may generally run at an optimal speed of 60FPS or exactly the screen refresh rate.
You may also want to learn more element.getBoundingClientRect () , which can provide information about the size and location of the HTML node.
Common mistake # 9: Copy the Ionic application model by hand
Ionic has a very specific design (almost entirely picture language). Especially with prototype products and in the early stages, we can save a lot of time and cost by taking advantage of appropriate components and styles. They are quite detailed and highly aesthetic.
The introduction of wire frames (wireframe) and mockup models have become the industry standard. Actually the application experience will be very different from just seeing a photo. Many designers, and both UX develop, are using tools like Axure or Balsamiq to quickly create wire frames (with little functionality).
Now Ionic developer has also released a similar tool called Ionic Creator dedicated to Ionic developers. The tool has a drag-and-drop web interface, and supports almost all of Ionic's core capabilities. This tool is superior in that it can export templates in multiple formats, with Ionic code running, you can even build and share applications. The application has a fee (but you can still use many free features).
Epilogue
Ionic revolutionized the hybrid application industry in an unbelievable way. However, over time, the methods and tools lacked a breakthrough. And as a result, developers have even more mistakes.
Ionic experts always have a way to develop parallel caliber applications across multiple platforms. This way requires you to take advantage of available tools, optimize performance, and follow the best practices.
Thank you to the wonderful Ionic community, including Michał Mikołajczyk , Mike Hartington (Ionic Core team) and Katie Ginder-Vogel (Marketing & Communications Manager, Ionic), for enabling me to make this article.