Over the last weeks we have been putting some effort on reducing the load time of our web applications. In the mobile world the two main suspects that usually come to mind are network and processing power, but it is not easy to considerably reduce requests and resource usage without cutting features from our users. So what if we could cut features that the user cannot see?
A quick analysis to our pages shows that, like many web applications, the user initially sees a much smaller amount of content than what we provide him. In our case, the ratio of initially visible content easily reached 1:13 in some of our main entry points. Below you can see a gross example of the three scenarios we tested and the viewport size of some popular mobile phones.
Pages b) and c) are two different scenarios of betting events. Unlike the previous example, these pages do not have many modules but are actually big lists with many betting possibilities. The difference between them is that page b) needs extra requests to render the whole list, while page c) fetches all the data in one request. Here we intended to find an easy way to render only a visible fraction of the list and make the list grow as the user scrolled down.
We ended up creating two AngularJS directives:
lazy-module – just place this attribute in any DOM element and instead of immediately render its content, this directive will make sure only a placeholder is rendered until the user is actually able to see it. This way you can save all the data fetching, scripting and rendering until the user scrolls this placeholder into the viewport. As soon as the placeholder is visible, the directive will start rendering the actual content. Since the browser may take some time in scripting and data fetching, choose a placeholder that gives the user some feedback of what is happening.
lazy-repeater – use this attribute at the same level where you are using any ng-repeat directive. Instead of having a huge list rendered all at once, you will now get a sublist approximately as big as your viewport. As the user approaches the end of the sublist, it will automatically double its size until the full list is rendered. This will postpone all the rendering until the user starts scrolling down the list and depending on the logic you have in each list item controller, you may also save some data requests since they will not be instantiated.
The results of applying just these two directives were quite impressive. With very little changes we achieved a considerable performance improvement. The table below shows the loading time improvements on all the above scenarios in both an i7 MacBook Pro (Google Chrome) and an older iPhone 4S (Safari).
|Improvement MBP||Improvement iPhone 4S||Directive used|
If you feel like trying this in your application, both directives were bundled into a package called ng-lazy-render. Try it and let us know what you think!