Last update on Saturday, January 12th 2019

Ionic 3 Performance Boost with Observable using VirtualScroll and WKWebView

What do you do when an application you just installed is f****** slow?
-------> Straight to the garbage, no question asked.
This scenario can also happen to the applications that you develop.
Not everybody has an iPhone 7.
In today's tuts we get this painful issue out of the way.

The objective is to go from this:
slow scroll no Ionic 3 virtual scroll
To this:
fast virtual scroll We will go through:
  • The unoptimized case
  • The WKWebView solution
  • The Ionic 3 VirtualScroll solution

Let's fire up our Ionic 3 app:

ionic start smoothapp blank --v2

The same home.ts file will be used for each case:

import { Component } from "@angular/core";
import { Observable } from "rxjs";

@Component({
  selector: "page-home",
  templateUrl: "home.html"
})
export class HomePage {
  displayedImages;

  constructor() {}

  ngOnInit() {
    const baseImg = "http://lorempixel.com/400/200/";
    const imgArray = Array(1000).fill(baseImg);

    this.displayedImages = Observable.of(imgArray);
  }
}

All the work is done in the ngOnInit hook.
I haven't found a free service that returns 1000 images on demand, so we go back to our good old lorempixel website.

First, we add 1000 image urls to a temporary array named imgArray.

Once this is done, an Observable is returned. A HTTP request now returns an Observable, that's why we return one to simulate this case (you can have a reminder on Observables there).

Using the method of from Observable, the image array will be transformed into an Observable sequence.

Just a good old ngFor

Ionic advises us to use the <ion-img> Component, however, it has some issues with the current VirtualScroll:

https://github.com/driftyco/ionic/issues/9660

So the good old <img> tag will be used to keep the tests congruency.

In the home.html:

<ion-content padding>
  <ion-list>
    <ion-item *ngFor="let displayedImage of displayedImages | async">

      <ion-avatar item-left>
        <img src="{{displayedImage}}">
      </ion-avatar>

    </ion-item>
  </ion-list>
</ion-content>

The images are displayed inside an <ion-list>.
The ngFor Directive here creates one <ion-item> for each image we have to display.
The asyncPipe is added because we are not looping on a simple array, but on an Observable sequence.

Finally the images are displayed inside an <ion-avatar>.

The benchmark:

with 10k with wkwebview

The initial part is the Ionic 3 loading screen with a stable 10 fps.
Once the application is loaded, the fps become unstable, every time a scroll is triggered, a fps drop appears.

It's looking very bad and that's not how a smooth application's benchmark should look like.
Let's fix this ;).

Introducing WKWebView

The WKWebView API was introduced in iOS 8.
It has a better HTML5 support (added IndexedDB and ObjectStore ArrayBuffer) and has far better performances than its predecessor UIWebView.

The whole installation process is available there:

https://github.com/driftyco/cordova-plugin-wkwebview-engine#installation-instructions

From here, 10k images will be displayed. Why? Because we can!

The results are really impressive:

with 10k with wkwebview

After the initial Ionic 3 loading (the constant 10fps).
The app is working smoothly averaging 55 fps!
All of that without modifying the source code. That's a quick and clean fix!

The Bleeding Edge: VirtualScroll

Finally the Ionic homemade solution: the VirtualScroll.

Unlike the other cases, the VirtualScroll only renders a limited number of rows.
Even though 10K images are available:

Ionic 3 Virtual Scroll restricted number

Only a few numbers are in the DOM.
This number is just enough to give the user the impression that every images are here.

The only changes are:

<ion-list [virtualScroll]="displayedImages | async">
    <ion-item *virtualItem="let displayedImage">
    .
    .
    .

The <ion-list> and the <ion-item>.
We attach the virtualScroll attribute. The displayedImages are required, alongside the asyncPipe (still using our Observable). The virtualItem Structural Directive will do its job but requires the creation of a displayedImage variable.

And that's it!

The performances: fps virtual scroll

The application is running smoothly while using the good old UIWebView API.

However, this solution comes with some other issues:

https://github.com/driftyco/ionic/issues/8744

Conclusion

We are damn lucky.
Many solutions and improvements have been created for us through the past years.
The VirtualScroll is very interesting because it allows us to virtually display thousands of images without breaking a sweat by only rendering a hundred, however, it does come with its own small issues that can be buzz killers.
On the other side, the WKWebView API is already there since iOS 8 and very stable for some great performances.
Always remember:

Speed is a requirement, not a feature -The Ionic Team

Introduction to Angular 7 Observables

This tuts will help
you master Angu...
...

Analyzing the Ionic AWS Full-Stack Starter: Configuration and Providers

Understand how
the Awesome Io...
...

Analyzing the Ionic AWS Full-Stack Starter: Custom APIs

The last step to
mastering the Io...
...

Stay up to date


Join over 4000 other developers who already receive my tutorials and their source code out of the oven with other free JavaScript courses and an Angular cheatsheet!
Designed by Jaqsdesign